前言:
三子棋是一种常见的民间传统游戏,游戏为双方对战,双方依次在9宫格棋盘上摆放棋子,率先将自己的三个棋子走成一条线视为胜利,其背后的逻辑并不难,接下来跟着C用C语言把三子棋写出来,跟电脑对对线可好?
初学C语言的小伙伴放心食用~~~
注意:为了方便,我将代码做了分块,他们分别是:
test.c :main函数所在项,用于整体的运行;
game.c : 实现游戏逻辑的项;
game.h : 声明函数的项.
目录
❤️1.整体框架
1.整体框架
基本框架类似于往期猜数字游戏
进入程序,输入1开始猜数字,输入0退出游戏,此处可用switch-case执行分支;
要使游戏至少能进行一次,可以使用do while循环;
这样可以先写出整体框架:
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> void menu() { printf("********************\n"); printf("* 1.play *\n"); printf("* 0.exit *\n"); printf("********************\n"); } int main() { int input = 0;//input要在do-while体系外 do { menu(); printf("请选择:"); scanf("%d", &input); switch (input)//1-真 0-假 可作判断条件 { case 1: //game(); printf("三子棋\n"); break; case 0: printf("退出游戏\n"); break; default: printf("选择错误,请重新选择\n"); break; } } while (input);//1-真 0-假 可作判断条件 return 0; }
运行:
整体框架完。
2.游戏逻辑
2.1数据的储存
要实现如下的棋盘
要储存数据,需要一个3*3的数组;
void game() { char board[3][3]; }
2.2初始化棋盘
我们发现初始状态下棋盘内都是空格,这就需要初始化,即把数组中的每个元素改为空格;
void init_board(char board[3][3], 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] = ' '; } } }
2.3打印棋盘
前面已经初始化了棋盘,再看一眼我们想要的棋盘
对,接下来要做的就是把那些杠杠(棋盘的边)打印出来:
我们把行中的数据+竖杠记为 1 ,分割行记为 2 ,1 和 2 的组合记为 3 ;
仔细观察可以发现,这些杠杠其实就是两个 3 加一个不带 2 的 3 组成的;
void print_board(char board[3][3], 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<row-1) printf("---|---|---\n"); } }
运行:
怎么样,是不是得到了完美的棋盘?
2.4下棋
下棋 其实就是把棋子( * # )放到初始化后的数组里面.
2.4.1玩家下棋
要输入的是:要下的棋所在空格的坐标
注意:1.坐标不能越界
2.不能用已占用的坐标
3.玩家眼中的坐标和程序员眼中的坐标
第一点:
可以用 if 语句,条件就是 x 和 y 都在 1~3 之间;
第二点:
用 if 语句,判断原来的坐标是否位空格;
第三点:
实现方法其实很简单:
输入的坐标是 (x,y)
实际更改的坐标是(x-1,y-1)
此部分代码如下:
void player_move(char board[3][3], int row, int col) { printf("玩家下棋\n"); while (1) { printf("请输入坐标:"); int x = 0; int y = 0; 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"); } } }
2.4.2电脑下棋
电脑随机生成坐标,只要未被占用就下棋;
随机数的生成不再赘述,详见往期猜数字游戏;
其余跟玩家下棋类似;
void computer_move(char board[3][3], int row, int col) { printf("电脑下棋\n"); while (1) { int x = rand() % row; int y = rand() % col; if (board[x][y] == ' ') { board[x][y] = '#'; break; } } }
2.5判断结局
判断输赢的代码要告诉我:玩家赢了?电脑赢了?平局?游戏继续?
像这种多情况的可以各接收一个返回值作为标识;
玩家赢:返回 * ;
电脑赢:返回 # ;
平局:返回 Q ;
游戏继续:返回 C ;
while (1) { player_move(board, 3, 3); print_board(board, 3, 3); //判断 ret = is_win(board, 3, 3); if (ret != 'C') { break; } computer_move(board, 3, 3); print_board(board, 3, 3); //判断 ret = is_win(board, 3, 3); if (ret != 'C') { break; } } if (ret == '*') printf("恭喜你赢了!!!\n"); if(ret=='#') printf("你输了\n"); if(ret=='Q') printf("平局\n");
2.5.1判断输赢
根据规则,赢的情况无非就三种:行,列,对角 三子连珠;
所以可以直接穷举 :
//判断行 int i = 0; for (i = 0; i < row; i++) { if (board[i][0] == board[i][1]&& board[i][1] == board[i][2] && board[i][0] != ' ') { return board[i][0]; } } //判断列 for (i = 0; i < col; i++) { if (board[0][i] == board[1][i]&& board[1][i] == board[2][i] && board[0][i] != ' ') { return board[0][i]; } } //判断对角线 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]; }
2.5.2平局
当输赢没有返回,且棋盘满了时就是平局;
判断每个位置是否为空格即可;
if (is_full(board, 3, 3) == 1) { return 'Q'; } int is_full(char board[3][3], 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; }
2.5.3继续
没有玩家或者电脑赢,也没有平局,游戏继续;
末尾返回C即可;
3.最终成果展示
test.c
#include"game.h" void menu() { printf("********************\n"); printf("* 1.play *\n"); printf("* 0.exit *\n"); printf("********************\n"); } void game() { char board[3][3]; init_board(board, 3, 3); print_board(board, 3, 3); char ret = 0; while (1) { player_move(board, 3, 3); print_board(board, 3, 3); //判断 ret = is_win(board, 3, 3); if (ret != 'C') { break; } computer_move(board, 3, 3); print_board(board, 3, 3); //判断 ret = is_win(board, 3, 3); if (ret != 'C') { break; } } if (ret == '*') printf("恭喜你赢了!!!\n"); else if(ret=='#') printf("你输了\n"); else if(ret=='Q') printf("平局\n"); } 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 1 #include"game.h" void init_board(char board[3][3], 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 print_board(char board[3][3], 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<row-1) printf("---|---|---\n"); } int n = 0; if(n > 1) { return; } } void player_move(char board[3][3], int row, int col) { printf("玩家下棋\n"); while (1) { printf("请输入坐标:"); int x = 0; int y = 0; 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 computer_move(char board[3][3], int row, int col) { printf("电脑下棋\n"); while (1) { int x = rand() % row; int y = rand() % col; if (x >= 1 && x <= row && y >= 1 && y <= col) { if (board[x][y] == ' ') { board[x][y] = '#'; break; } } } } static int is_full(char board[3][3], 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 is_win(char board[3][3], 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][0] != ' ') { return board[i][0]; } } //判断列 for (i = 0; i < col; i++) { if (board[0][i] == board[1][i]&& board[1][i] == board[2][i] && board[0][i] != ' ') { return board[0][i]; } } //判断对角线 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 (is_full(board, 3, 3) == 1) { return 'Q'; } //继续 return 'C'; }
game.h
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<stdlib.h> #include<time.h> //声明函数 //初始化棋盘 void init_board(char board[3][3], int row, int col); //打印棋盘 void print_board(char board[3][3], int row, int col); //玩家下棋 void player_move(char board[3][3], int row, int col); //电脑下棋 void computer_move(char board[3][3], int row, int col); //判断输赢 char is_win(char board[3][3], int row, int col);
如果你觉得这篇文章还不错并且对你有帮助,不妨动动手指点赞收藏加转发,给一个大大的关注
你们的每一次支持都将转化为我前进的动力!!!💗💗💗