C语言三子棋
整体框架游戏框架具体实现
初始化棋盘打印棋盘玩家下棋电脑下棋判断胜负
完整代码
分成三个文件进行编写
test.c 、
game.h 、
game.c
test.c :用于实现总体框架,及测试代码
game.h :用于符号定义、函数声明、头文件引用
game.c :用实现游戏代码
代码并不复杂这里简单的讲一下
代码运行过程如下:
代码运行 ⟹ Longrightarrow ⟹ 打印菜单 ⟹ Longrightarrow ⟹ 玩家选择 ⟹ Longrightarrow ⟹ 开始游戏 ⟹ Longrightarrow ⟹ 初始化棋盘 ⟹ Longrightarrow ⟹ 打印棋盘 ⟹ Longrightarrow ⟹ 玩家电脑下棋及判断胜负 ⟹ Longrightarrow ⟹ 结束 ⟹ Longrightarrow ⟹ 再次打印菜单决定是否继续 ⟹ Longrightarrow ⟹ 结束
整体框架首先打印菜单供玩家进行选择
选择1: 进入游戏,游戏结束,break 跳出多分支 此时 input 值为 1,循环继续。实现了玩了一把不过瘾再玩一把的需求选择0: 打印提示 break 跳出多分支 此时 input 值为 0,循环停止。程序结束选择其它:打印提示 break 跳出多分支 此时 input 值为 非0,循环继续
// 创建菜单 -- 可自行修改为想要的样式 void menu() { printf("**************************n"); printf("******** 1.play ********n"); printf("******** 0.exit ********n"); printf("**************************n"); } int main() { int input = 0; srand((unsigned int)time(NULL)); // 用于设置随机数种子 do { menu(); printf("请选择:>"); scanf("%d", &input); switch (input) { case 1: system("cls"); // 清屏 - 可以加在自己想要的地方 game(); break; case 0: printf("退出游戏n"); break; default: printf("选择错误,请重输n"); break; } } while (input); return 0; }游戏框架
理清游戏的执行顺序
定义棋盘大小
存储棋局的信息
采用 #define 是为了方便管理,以后可以方便修改为 4 * 4、5 * 5
#define ROW 3 // 定义棋盘行数 #define COL 3 // 定义棋盘列数
初始化棋盘
将全部元素赋值为 空格 ,为游戏进行做好准备
打印棋盘
按照自己喜欢的格式打印棋盘
下棋
实现人机对弈,每走一步,重新打印棋盘,并判断游戏是否结束
// 游戏实现 void game() { // 用于存储棋盘信息 char board[ROW][COL] = { 0 }; // 用于存储棋局状态 char ret = 0; // 初始化棋盘 --- 也可以使用库函数 memset 快速设置,记得在 game.h 中引用头文件 #include具体实现 初始化棋盘InitBoard(board, ROW, COL); // memset(board, ' ', ROW * COL * sizeof(board[0][0])); // 打印棋盘 PrintBoard(board, ROW, COL); while (1) { // 玩家下棋 PlayerMove(board, ROW, COL); PrintBoard(board, ROW, COL); ret = IsWin(board, ROW, COL); if (ret != 'C') break; // 电脑下棋 ComputerMove(board, ROW, COL); PrintBoard(board, ROW, COL); ret = IsWin(board, ROW, COL); if (ret != 'C') break; } // 判断最终结果 if ('*' == ret) printf("玩家赢n"); else if ('#' == ret) printf("电脑赢n"); else printf("平局n"); }
将元素全部赋值为 空格
// 按指定格式初始化棋盘 void InitBoard(char board[ROW][COL], int row, int col) { int i = 0; for (i = 0; i < row; i++) { int j = 0; for (j = 0; j < col; j++) { board[i][j] = ' '; // 全部初始化为空 } } }打印棋盘
注意格式
// 打印棋盘生成格式如下 - 可自行修改为自己想要的样子 // | | // ---|---|--- // | | // ---|---|--- // | | void PrintBoard(char board[ROW][COL], int row, int col) { int i = 0; for (i = 0; i < row; i++) { int j = 0; // 打印 " c | c | c " -- c 代表打印我们存在数组里的字符 for (j = 0; j < col; j++) { printf(" %c ", board[i][j]); if (j < col - 1) printf("|"); } printf("n"); // 打印 "---|---|---" if (i < row - 1) { for (j = 0; j < col; j++) { printf("---"); if (j < col - 1) printf("|"); } printf("n"); } } }玩家下棋
提示玩家输入要下的地方,并对坐标是否合法,是否已经落子进行判断,直到在正确的地方落下棋子,退出循环
玩家棋子为 ‘*’
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); // 以正常人的思维坐标应该从1开始,而不是0 if (x >= 1 && x <= row && y >= 1 && y <= col) { // 判断该坐标是否已落子 if (' ' == board[x - 1][y - 1]) { system("cls"); // 清屏 - 可以加在自己想要的地方 board[x - 1][y - 1] = '*'; break; } else { printf("该坐标已落子,请重输n"); } } else { printf("输入坐标不合法,请重输n"); } } }电脑下棋
电脑采用随机下棋,获取两个随机值
电脑的棋子为 ‘#’
关于C语言如何生成随机值: C语言获取随机数 (现在还没写,链接有时间再补。)
void ComputerMove(char board[ROW][COL], int row, int col) { printf("电脑下棋:>n"); Sleep(1000); // 睡眠 - 单位 ms 可自行修改 system("cls"); // 清屏 - 可以加在自己想要的地方 while (1) { // 电脑随机生成坐标 -- 生成坐标一定合法,无需再判断 int x = rand() % row; // 生成 0 ~ row - 1 int y = rand() % col; // 生成 0 ~ col - 1 // 判断是否已落子 if (' ' == board[x][y]) { board[x][y] = '#'; break; } } }判断胜负
无非就是遍历棋盘,看看是不是有一行相同,一列相同,对交线相同,或者平局,不然游戏继续
如果一行、一列、对交线相同,直接返回所对应的字符 ----- 字符即为玩家的棋子
最后根据所返回的字符进行判断,是继续游戏还是,结束游戏,宣布胜负
这里 IsWin() 函数由于写死了,只能用于判断 3 * 3 的棋盘
毕竟当初只是为了写三子棋就没怎么考虑,况且也没有什么 四子棋、五子棋(5 * 5 棋盘)吧
但为了扩展实现了一个对 多 * 多 棋盘的判断 ,定义了一个名字相同的函数,根据不同需求决定使用哪一个
// 判断棋盘是否已满 // 返回0,表示棋盘未满 // 返回1,表示棋盘已满 static int IsFull(char board[ROW][COL], int row, int col) { int i = 0; for (i = 0; i < row; i++) { int j = 0; for (j = 0; j < col; j++) { if (' ' == board[i][j]) return 0; } } return 1; } // 玩家赢,返回 '*' // 电脑赢,返回 '#' // 平局, 返回 'Q' // 继续, 返回 'C' // 仅用于 3 * 3 棋盘 char IsWin(char board[ROW][COL], int row, int col) { int i = 0; // 判断列相等 for (i = 0; i < col; i++) { if (board[0][i] != ' ' && board[0][i] == board[1][i] && board[1][i] == board[2][i]) return board[1][i]; } // 判断行相等 for (i = 0; i < row; i++) { if (board[i][0] != ' ' && board[i][0] == board[i][1] && board[i][1] == board[i][2]) return board[i][1]; } // 判断对角线相等 if (board[0][0] != ' ' && board[0][0] == board[1][1] && board[1][1] == board[2][2]) return board[1][1]; if (board[0][2] != ' ' && board[0][2] == board[1][1] && board[1][1] == board[2][0]) return board[1][1]; // 判断平局 if (1 == IsFull(board, row, col)) return 'Q'; // 游戏继续 -- 以上条件都不成立,游戏尚未结束 return 'C'; }
//用于 多 * 多棋盘判定 char IsWin(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][0] || board[i][0] != board[i][j]) break; } if (col == j) return board[i][0]; } // 判断列相等 for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { if (' ' == board[0][i] || board[0][i] != board[j][i]) break; } if (col == j) return board[0][i]; } // 判断主对角线相等 for (i = 1; i < col; i++) { if (' ' == board[0][0] || board[0][0] != board[i][i]) break; } if (col == i) return board[0][0]; // 判断副对角线相等 for (i = 1; i < col; i++) { if (' ' == board[0][col - 1] || board[0][col - 1] != board[i][col - i - 1]) break; } if (col == i) return board[0][col - 1]; // 判断平局 if (1 == IsFull(board, row, col)) return 'Q'; // 游戏继续 return 'C'; }完整代码
test.c
#include "game.h" // 引用自己编写的头文件 // 创建菜单 -- 可自行修改为想要的样式 void menu() { printf("**************************n"); printf("******** 1.play ********n"); printf("******** 0.exit ********n"); printf("**************************n"); } // 游戏实现 void game() { // 用于存储棋盘信息 char board[ROW][COL] = { 0 }; // 用于存储棋局状态 char ret = 0; // 初始化棋盘 --- 也可以使用库函数 memset 快速设置,记得在 game.h 中引用头文件 #includeInitBoard(board, ROW, COL); // memset(board, ' ', ROW * COL * sizeof(board[0][0])); // 打印棋盘 PrintBoard(board, ROW, COL); while (1) { // 玩家下棋 PlayerMove(board, ROW, COL); PrintBoard(board, ROW, COL); ret = IsWin(board, ROW, COL); if (ret != 'C') break; // 电脑下棋 ComputerMove(board, ROW, COL); PrintBoard(board, ROW, COL); ret = IsWin(board, ROW, COL); if (ret != 'C') break; } // 判断最终结果 if ('*' == ret) printf("玩家赢n"); else if ('#' == ret) printf("电脑赢n"); else printf("平局n"); } int main() { int input = 0; srand((unsigned int)time(NULL)); // 用于设置随机数种子 do { menu(); printf("请选择:>"); scanf("%d", &input); switch (input) { case 1: system("cls"); // 清屏 - 可以加在自己想要的地方 game(); break; case 0: printf("退出游戏n"); break; default: printf("选择错误,请重输n"); break; } } while (input); return 0; }
game.h 头文件
#pragma once // 防止头文件被重复包含 #define _CRT_SECURE_NO_WARNINGS 1 // 屏蔽 VS 报错 #include#include #include #include #define ROW 3 // 定义棋盘行数 #define COL 3 // 定义棋盘列数 // 初始化棋盘 void InitBoard(char board[ROW][COL], int row, int col); // 打印棋盘 void PrintBoard(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); // 判断胜负 char IsWin(char board[ROW][COL], int row, int col);
game.c
#include "game.h" // 引用自己编写的头文件 // 按指定格式初始化棋盘 void InitBoard(char board[ROW][COL], int row, int col) { int i = 0; for (i = 0; i < row; i++) { int j = 0; for (j = 0; j < col; j++) { board[i][j] = ' '; // 全部初始化为空 } } } // 打印棋盘生成格式如下 - 可自行修改为自己想要的样子 // | | // ---|---|--- // | | // ---|---|--- // | | void PrintBoard(char board[ROW][COL], int row, int col) { int i = 0; for (i = 0; i < row; i++) { int j = 0; // 打印 " c | c | c " -- c 代表打印我们存在数组里的字符 for (j = 0; j < col; j++) { printf(" %c ", board[i][j]); if (j < col - 1) printf("|"); } printf("n"); // 打印 "---|---|---" if (i < row - 1) { for (j = 0; j < col; j++) { printf("---"); if (j < col - 1) printf("|"); } printf("n"); } } } 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); // 以正常人的思维坐标应该从1开始,而不是0 if (x >= 1 && x <= row && y >= 1 && y <= col) { // 判断该坐标是否已落子 if (' ' == board[x - 1][y - 1]) { system("cls"); // 清屏 - 可以加在自己想要的地方 board[x - 1][y - 1] = '*'; break; } else { printf("该坐标已落子,请重输n"); } } else { printf("输入坐标不合法,请重输n"); } } } void ComputerMove(char board[ROW][COL], int row, int col) { printf("电脑下棋:>n"); Sleep(1000); // 睡眠 - 单位 ms 可自行修改 system("cls"); // 清屏 - 可以加在自己想要的地方 while (1) { // 电脑随机生成坐标 -- 生成坐标一定合法,无需再判断 int x = rand() % row; // 生成 0 ~ row - 1 int y = rand() % col; // 生成 0 ~ col - 1 // 判断是否已落子 if (' ' == board[x][y]) { board[x][y] = '#'; break; } } } // 判断棋盘是否已满 // 返回0,表示棋盘未满 // 返回1,表示棋盘已满 static int IsFull(char board[ROW][COL], int row, int col) { int i = 0; for (i = 0; i < row; i++) { int j = 0; for (j = 0; j < col; j++) { if (' ' == board[i][j]) return 0; } } return 1; } // 玩家赢,返回 '*' // 电脑赢,返回 '#' // 平局, 返回 'Q' // 继续, 返回 'C' // 仅用于 3 * 3 棋盘 char IsWin(char board[ROW][COL], int row, int col) { int i = 0; // 判断列相等 for (i = 0; i < col; i++) { if (board[0][i] != ' ' && board[0][i] == board[1][i] && board[1][i] == board[2][i]) return board[1][i]; } // 判断行相等 for (i = 0; i < row; i++) { if (board[i][0] != ' ' && board[i][0] == board[i][1] && board[i][1] == board[i][2]) return board[i][1]; } // 判断对角线相等 if (board[0][0] != ' ' && board[0][0] == board[1][1] && board[1][1] == board[2][2]) return board[1][1]; if (board[0][2] != ' ' && board[0][2] == board[1][1] && board[1][1] == board[2][0]) return board[1][1]; // 判断平局 if (1 == IsFull(board, row, col)) return 'Q'; // 游戏继续 -- 以上条件都不成立,游戏尚未结束 return 'C'; } // 用于 多 * 多棋盘判定 //char IsWin(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][0] || board[i][0] != board[i][j]) // break; // } // if (col == j) // return board[i][0]; // } // // // 判断列相等 // for (i = 0; i < row; i++) // { // for (j = 0; j < col; j++) // { // if (' ' == board[0][i] || board[0][i] != board[j][i]) // break; // } // if (col == j) // return board[0][i]; // } // // // 判断主对角线相等 - 起始坐标取左上角 ->(0,0) // for (i = 1; i < col; i++) // { // if (' ' == board[0][0] || board[0][0] != board[i][i]) // break; // } // if (col == i) // return board[0][0]; // // // 判断副对角线相等 - 起始坐标取右上角 ->(0,col - 1) // for (i = 1; i < col; i++) // { // if (' ' == board[0][col - 1] || board[0][col - 1] != board[i][col - i - 1]) // break; // } // if (col == i) // return board[0][col - 1]; // // // 判断平局 // if (1 == IsFull(board, row, col)) // return 'Q'; // // // 游戏继续 // return 'C'; //}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)