700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 【C语言入门简单程序】三子棋——新手轻松学

【C语言入门简单程序】三子棋——新手轻松学

时间:2022-07-18 05:32:58

相关推荐

【C语言入门简单程序】三子棋——新手轻松学

目录

设计思路

功能实现

展示棋盘 Show_board

棋盘的初始化 Initial_Board

玩家下棋 Player_Move

电脑下棋 Computer_Move

判断棋局

优化与改进

判定胜出的优化

提升效率的小设计

设计思路

在设计整个程序前,我们要先思考出整个程序设计的框架,三子棋游戏的流程是什么,具体需要什么函数来实现每一步的功能。

根据经验来看,首先需要一个菜单功能来确定玩家想要进入游戏,而非误触等操作。

在进入游戏后,我们可以选择单人模式或双人模式,单机和电脑玩,设计出来和朋友一起玩。

(带一点凡尔赛性质,是不是瞬间在朋友面前就高大起来了!那就接着看下去吧!

在单机模式下,在我们出子之后,需要电脑出子,

出子完毕后需要通过当前的棋盘判断下一次落子的位置

当有三个棋子连成一条线时,判定胜利。

至此我们可以分析出来,这个游戏需要实现的功能有:玩家下棋、电脑下棋、展示棋盘、判断棋局。

功能实现

首先建立三个文件,包含相应的函数

test.c——测试

game.h——函数的声明

game.c——函数的实现

之后我们实现相应的功能。

展示棋盘 Show_board

首先我们需要对棋盘进行设计,通过打印,分割出九个格子,实现简单的可视化。

void Show_board(char board[ROW][COL], int r, int c){int i = 0;for (int i = 0; i < ROW; i++){for (int j = 0; j < COL; j++){printf(" %c ", board[i][j]);if(j<COL-1) printf("|");else printf("\n");}for (int k = 0; k < ROW; k++){if (i < ROW - 1){printf("---");if (k < COL - 1)printf("|");else printf("\n");}}}}

打印后就是这个样子啦。

棋盘的初始化 Initial_Board

我们通过一个3*3的二维数组存储用户输入来实现三子棋的落子,在此之前,先对没有下过子的棋盘进行初始化。为简明起见,我们这里将数组中的每一个元素设置为空。

void Initinal_Board(char board[ROW][COL], int r, int c){for (int i = 0; i < r; i++){for (int j = 0; j < c; j++){board[i][j] = ' ';}}}

玩家下棋 Player_Move

用一个字符表示玩家下棋。对于玩家来说,玩家并没有“这是用数组模拟实现的一个小游戏,而数组的下标是从零开始”的意识,为了服务用户,我们这里将用户输入的数-1后的值记为真实的坐标值。当用户输入有误时,提醒用户。

void Player_Move(char board[ROW][COL], int r, int c){int x = 0;int y = 0;printf("\n--------玩家的回合-------\n");printf("请输入落子的位置->x:__ y:__\n");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] = 'p';}else{printf("该位置已被占用");}}else{printf("不能下在这里!输入的坐标有误\n");}Show_board(board, ROW, COL);}

电脑下棋 Computer_Move

这里我们仅仅实现一个傻瓜操作,电脑:哪里有空下哪里!

void Computer_Move(char board[ROW][COL], int r, int c){printf("\n-------电脑的回合:-------\n");Sleep(500);while (1){int x = rand() % 3;int y = rand() % 3;if (board[x][y] == ' '){board[x][y] = 'c';break;}}Show_board(board, ROW, COL);}

判断棋局

这里比较复杂,我们需要判断棋盘是否有三子连成一条线,而三子连线可能有三种情况:行相连、列相连,对角线相连。

如果没有,查看棋盘是否为“满”的状态。

如果有三子连成一条线,判断是电脑胜出还是玩家胜出。

char is_win(char board[ROW][COL], int r, int c){int i = 0;//行相同for (i = 0; i < ROW; i++){if (board[i][0] == board[i][1] == board[i][2] &&board[i][0] !=' ')return board[i][0];}//列相同for (i = 0; i < ROW; i++){if (board[0][i] == board[1][i] == board[2][i]&&board[0][i]!=' ')return board[i][0];}//对角线1for (i = 0; i < ROW; i++){if (board[0][0] == board[1][1] == board[2][2]&&board[0][0]!=' ')return board[i][0];}//对角线2for (i = 0; i < ROW; i++){if (board[0][2] == board[1][1] == board[2][0] && board[0][0] != ' ')return board[i][0];}//判断平局if (is_full(board, ROW, COL) == 1){return 'Q';}return 'c';}

优化与改进

判定胜出的优化

之前的代码仅适用于三子棋,复用性差,因此我们做一个很挫但有用的提升版本,欢迎各位佬多多指教。(这个版本的优化真的很挫,但是我尽力了)

void Judge(char board[ROW][COL], int r, int c){//判断行或列 是否连成x子for (int i = 0; i < r; i++){int countp1 = 0;int countc1 = 0;int countp2 = 0;int countc2 = 0;for (int j = 0; j < c; j++){if (board[i][j] == board[i][j + 1] && j + 1 < c ){if (board[i][j] == 'c') countc1++;if (board[i][j] == 'p') countp1++;}if (board[j][i] == board[j+1][i] && j+1 < r && board[i][j] != ' '){if (board[i][j] == 'c') countc2++;if (board[i][j] == 'p') countp2++;}}if (countc1 == c - 1 || countc2 == c - 1) return Player;if (countp1 == r - 1 || countp2 == r - 1) return Computer;}//判断两条对角线for (int i = 0; i < c; i++){int countc1 = 0;int countc2 = 0;int countp1 = 0;int countp2 = 0;for (int j = 0; j < r; j++){if (i == j && board[i][j] == 'c') countc1++;if (i == j && board[i][j] == 'p') countp1++;if (i + j == r && board[i][j] == 'c') countc2++;if (i + j == r && board[i][j] == 'p') countp2++;}if (countc1 == r || countc2 == c) return Player;if (countp1 == r || countp2 == c) return Computer;}//判断是否为“满”int count = 0;for (int i = 0; i < ROW; i++){int j = 0;for (j = 0; j < COL; j++){if (board[i][j] == ' '){return Continue;}else count++;}}if (count++ != 0) return Equal;//接着玩return Continue;}

提升效率的小设计

使用enum定义棋局判断常量

当你不知道枚举类型到底有什么用的时候,它来了,它来了,它带着代码的易读性走来了。

使用define定义宏

#define CASE break;case//避免因忘记break而出错int main(){int input = 0;srand((unsigned int)time(NULL));do {menu();printf("请选择->");scanf("%d", &input);switch (input){CASE 0:printf("退出游戏\n");CASE 1 :game();default:printf("输入错误");break;}} while (input);}

双人模式

增设一个Player1_Move()和Player2_Move(),并修改游戏细节。

void menu(){printf("\n");printf("*********************\n");printf("********0.EXIT*******\n");printf("****1.ONE PLAYER*****\n");printf("****2.TWO PLAYER*****\n");printf("*********************\n");printf("\n");}

debug

在测试时发现了如下问题:在单击模式下,如果玩家输入错误,将自动延顺至电脑的回合。

解决这个问题我们只需要在玩家下棋的函数中嵌套Player_Move()

怎么样是不是很简单呢,快码起代码叫你的朋友和你一起来玩吧!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。