c语言|n子棋,你能下赢电脑吗,来玩玩吧

我又来啦,看到上一篇扫雷小游戏大家很感兴趣,这里就在写一个关于n子棋的小游戏吧!
废话不多说
直接上思路
c语言|n子棋,你能下赢电脑吗,来玩玩吧
文章图片

这里也会涉及到三个文件哦,注意代码写的位置!

n子棋的实现

  • 1.游戏开始界面及选择选项
    • 1.1菜单
    • 1.2选择是否玩游戏(需要在game.c里实现游戏所有功能)
      • 1.2.1玩家选择玩游戏
        • 1.2.1.1初始化键盘
        • 1.2.1.2展示棋盘
        • 1.2.1.3真正的玩家和电脑开始下棋!!!(最难的地方)
  • 2.小结
  • 3.一次性展示完整的代码(需要源码的自取,之前的两篇博客忘记了添加这一步了,需要的也可以私我)

1.游戏开始界面及选择选项 1.1菜单
//test.c void menu() { printf("*****************************\n"); printf("*****1. play0. exit *****\n"); printf("*****************************\n"); }

ps:
这种菜单基本上适用于自己写的一些小游戏,可以记住这个写法哦
1.2选择是否玩游戏(需要在game.c里实现游戏所有功能)
//test.c int main() { int input = 0; do { menu(); //打印菜单 printf("请选择:>"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出游戏\n"); break; default: printf("选择错误!\n"); break; } } while (input); return 0; }

ps:
整体是使用的switch来实现选择的功能,写法很简单,这里提一下while(input)这样写的妙处。
但玩家想玩游戏时并且想有多次玩游戏的机会,会输入1,而while(1)为真,故一直在循环里。而当输入0,跳出循环,正好满足的玩家不想玩游戏的想法
1.2.1玩家选择玩游戏
#test.c void game() { char ret = 0; char board[ROW][COL] = { 0 }; //初始化棋盘的函数 InitBoard(board, ROW, COL); DispalyBoard(board, ROW, COL); //下棋 while (1) { PlayerMove(board, ROW, COL); //判断输赢 ret = IsWin(board, ROW, COL); if (ret != 'C') { break; } DispalyBoard(board, ROW, COL); ComputerMove(board, ROW, COL); //判断输赢 ret = IsWin(board, ROW, COL); if (ret != 'C') { break; } DispalyBoard(board, ROW, COL); } if (ret == '*') { printf("玩家赢\n"); } else if (ret == '#') { printf("电脑赢\n"); } else { printf("平局\n"); } DispalyBoard(board, ROW, COL); }

【c语言|n子棋,你能下赢电脑吗,来玩玩吧】ps:这里是整个game的思路,具体功能得在game.c里实现
1.2.1.1初始化键盘
//game.c void InitBoard(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { board[i][j] = ' '; } } }

ps:
最开始创建数组的时候,给数组的是0,这里为了展示棋盘,所以要放空格进去。
1.2.1.2展示棋盘
//game.c //第一个版本 //void DispalyBoard(char board[ROW][COL], int row, int col) //{ // int i = 0; // for (i = 0; i < row; i++) // { ////打印数据 //printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]); ////打印分割信息 //if(i

ps:这里对棋盘的理解是个重点,先看看棋盘该有的样子吧
c语言|n子棋,你能下赢电脑吗,来玩玩吧
文章图片

第一个版本的写法,是将棋盘理解成五行五列,而第二个版本,是用2 2 1的方式来理解五行五列,整体效果一样,都可以完美的打印出来
1.2.1.3真正的玩家和电脑开始下棋!!!(最难的地方)
//game.c void PlayerMove(char board[ROW][COL], int row, int col) { int x = 0; int y = 0; printf("玩家下棋:>\n"); while (1) { printf("请输入坐标:>"); scanf("%d %d", &x, &y); //坐标范围合法的判断 if (x >= 1 && x <= row && y >= 1 && y <= col) { if (board[x - 1][y - 1] == ' ') { board[x - 1][y - 1] = '*'; break; } else { printf("坐标被占用,不能下棋,请选择其他位置\n"); } } else { printf("坐标非法,请重新输入\n"); } } }void ComputerMove(char board[ROW][COL], int row, int col) { printf("电脑下棋:>\n"); int x = 0; int y = 0; while (1) { x = rand() % row; //0~2 y = rand() % col; //0~2 if (board[x][y] == ' ') { board[x][y] = '#'; break; } } }//满了就返回1 //不满返回0 int IsFull(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { if (board[i][j] == ' ') { return 0; } } } return 1; }char IsWin(char board[ROW][COL], int row, int col) { //行 int i = 0; for (i = 0; i < row; i++) { if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ') { return board[i][1]; // } } //列 int j = 0; for (j = 0; j < col; j++) { if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' ') { return board[1][j]; } } //对角线 if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ') { return board[1][1]; } if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ') { return board[1][1]; } //没有人赢,就要平局 if (IsFull(board, row, col)) { return 'Q'; } //游戏继续 return 'C'; } //test.c int main() { srand((unsigned int)time(NULL)); //设置随机数的生成起点的 int input = 0; do { menu(); //打印菜单 printf("请选择:>"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出游戏\n"); break; default: printf("选择错误!\n"); break; } } while (input); return 0; }

ps:
1.先分析玩家下棋的时候,注意我们是为了给别人完,并不是所有的人都懂数组特殊之处(下标从0开始),所有我们要人性化一点,将玩家输入的正常坐标减1来对应到真正的数组位置
2.玩家和电脑每一次下棋的时候,都要判断该位置是否已经下过了或者说坐标超出数组范围了,这一点很重要
3.在看电脑下棋,这里有了一个常见而且重要的点就是生成足够随机的随机数,所以这个方法一定要一上手就能写出来
4.最后一点就是判断输赢了,这个函数需要判断横着一条线,竖着一条线,斜着的两条线,是否能满足一方获胜,或者数组已经满了,只能判成平局了。还有就是此刻没有胜出,数组也没满,继续游戏
2.小结 1.game.h文件内可以宏定义一下棋盘的行和列,如果以后想改变游戏难度的话,可以在这里一键改变棋盘大小,很省事!
2.由于game.c和test.c中需要include的一些文件都是共同的,而且都要引用game.h,所以可以将这二者需要include的全部放到game.h,最后引用game,h就好了
3.最后就是想说,没有完美的代码,代码有什么问题或者没有理解代码的意思的都欢迎评论或者私信我,我很期待你们的看法,也再次感谢大家能来看我的博客,不妨点个关注,我们下期再见!
3.一次性展示完整的代码(需要源码的自取,之前的两篇博客忘记了添加这一步了,需要的也可以私我)
//test.c #define _CRT_SECURE_NO_WARNINGS#include "game.h"void menu() { printf("*****************************\n"); printf("*****1. play0. exit *****\n"); printf("*****************************\n"); }void game() { char ret = 0; char board[ROW][COL] = { 0 }; //初始化棋盘的函数 InitBoard(board, ROW, COL); DispalyBoard(board, ROW, COL); //下棋 while (1) { PlayerMove(board, ROW, COL); //判断输赢 ret = IsWin(board, ROW, COL); if (ret != 'C') { break; } DispalyBoard(board, ROW, COL); ComputerMove(board, ROW, COL); //判断输赢 ret = IsWin(board, ROW, COL); if (ret != 'C') { break; } DispalyBoard(board, ROW, COL); } if (ret == '*') { printf("玩家赢\n"); } else if (ret == '#') { printf("电脑赢\n"); } else { printf("平局\n"); } DispalyBoard(board, ROW, COL); }int main() { srand((unsigned int)time(NULL)); //设置随机数的生成起点的 int input = 0; do { menu(); //打印菜单 printf("请选择:>"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出游戏\n"); break; default: printf("选择错误!\n"); break; } } while (input); return 0; }

//game.c #define _CRT_SECURE_NO_WARNINGS #include "game.h"void InitBoard(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { board[i][j] = ' '; } } }//第一个版本 //void DispalyBoard(char board[ROW][COL], int row, int col) //{ // int i = 0; // for (i = 0; i < row; i++) // { ////打印数据 //printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]); ////打印分割信息 //if(i\n"); while (1) { printf("请输入坐标:>"); scanf("%d %d", &x, &y); //坐标范围合法的判断 if (x >= 1 && x <= row && y >= 1 && y <= col) { if (board[x - 1][y - 1] == ' ') { board[x - 1][y - 1] = '*'; break; } else { printf("坐标被占用,不能下棋,请选择其他位置\n"); } } else { printf("坐标非法,请重新输入\n"); } } }void ComputerMove(char board[ROW][COL], int row, int col) { printf("电脑下棋:>\n"); int x = 0; int y = 0; while (1) { x = rand() % row; //0~2 y = rand() % col; //0~2 if (board[x][y] == ' ') { board[x][y] = '#'; break; } } }//满了就返回1 //不满返回0 int IsFull(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { if (board[i][j] == ' ') { return 0; } } } return 1; }char IsWin(char board[ROW][COL], int row, int col) { //行 int i = 0; for (i = 0; i < row; i++) { if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ') { return board[i][1]; // } } //列 int j = 0; for (j = 0; j < col; j++) { if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' ') { return board[1][j]; } } //对角线 if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ') { return board[1][1]; } if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ') { return board[1][1]; } //没有人赢,就要平局 if (IsFull(board, row, col)) { return 'Q'; } //游戏继续 return 'C'; }

//game.h #pragma once#include .h> #include .h> #include #define ROW 3 #define COL 3//初始化棋盘 void InitBoard(char board[ROW][COL], int row, int col); //打印棋盘 void DispalyBoard(char board[ROW][COL], int row, int col); //玩家下棋 void PlayerMove(char board[ROW][COL], int row, int col); //电脑下棋 //找没有下棋的随机下棋 void ComputerMove(char board[ROW][COL], int row, int col); // //玩家赢 - '*' //电脑赢 - '#' //平局 - 'Q' //继续 - 'C' //char IsWin(char board[ROW][COL], int row, int col);

    推荐阅读