赞
踩
相信很多同学在学了一小部分C语言之后,总是对自己的能力有疑问,不知道自己现在是什么水平,大家可以尝试一下博主的简易的三子棋游戏,大家可以去练练手。下面是博主的三子棋游戏实现的主要步骤(博主的篇幅可能较大,但是很详细,希望大家能看完。)
1.第一步是打印菜单,选择1是开始游戏,选择2是退出游戏
- void menu()
- {
- printf("########################\n");
- printf("#######1.开始游戏#######\n");
- printf("#######2.退出游戏#######\n");
- printf("########################\n");
- }
2.第二步是在打印玩菜单之后,要用循环语句来实现游戏(用循环语句的原因是:可以多次玩,而不是玩一次就玩完了)
- int main()
- {
- int input = 0;
- srand((unsigned int)time(NULL));
- printf("请输入数字:->\n");
- do
- {
- menu();
- scanf("%d", &input);
- switch (input) {
- case 1:
- printf("开始游戏\n");
- game();
- break;
- case 2:
- printf("退出游戏\n");
- input = 0;
- break;
- default:
- printf("选择错误,请重新选择\n");
- break;
- }
- } while (input);
- return 0;
- }

这里让玩家从键盘输入的值来作为循环判断的条件,这样就可以实现让玩家选择玩还是不玩 (这里的srand可能大家不知道是什么,不要着急,下面会讲它的具体使用)
下面的是主体代码,这里博主采用了分模块的形式去完成这个游戏(模块化的好处是可以让整个程序看起来有层次感,让大家更容易看懂理解)
所有要用到的方法的声明、引用的头文件和常量的声明,博主都放在了"game.h"的头文件中
- #pragma once
- #define ROW 3
- #define COL 3
- #include<stdio.h>
- #include<string.h>
- #include<time.h>
- #include<stdlib.h>
-
- //键盘的初始化
- void Initboard(char board[ROW][COL], int row, int col);
-
- //棋盘的打印:
- void Displayboard(char board[ROW][COL], int row, int col);
-
- //玩家下棋
- void Player_move(char board[ROW][COL], int row, int col);
-
- //电脑下棋
- void Computer_move(char board[ROW][COL],int row,int col);
-
- //判断胜负
- char Win(char board[ROW][COL], int row, int col);
-
- //判断平局
- int Full(char board[ROW][COL], int row, int col);
-
- //电脑拦截
- void simplealgorithm(char board[ROW][COL], int row, int col, int* x,int* y);

这里把棋盘的行(ROW)和列(COL)采用了宏定义,就是为了以后方便其他的程序猿对棋盘的扩展,到时候要拓展只能在这里改一下就可以了,而不用去每个用到行和列的地方去逐一更改,这样节约了大把时间。
这里放了所有在"game.h"中声明的方法的实现
- #include"game.h"
-
- void Initboard(char board[ROW][COL],int row,int col)
- {
- memset(board, ' ', row * col);
- }
-
- void Displayboard(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++)
- {
- //打印数据
- 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 Player_move(char board[ROW][COL], int row, int col)
- {
- int x = 0;//棋子的坐标
- int y = 0;
- printf("玩家下棋:\n");
- while (1)
- {
- 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");
- continue;
- }
- }
- else
- printf("坐标非法,请重新输入\n");
- }
-
- }
-
- void Computer_move(char board[ROW][COL], int row, int col)
- {
- int x = 0, y = 0;
- printf("电脑下棋:\n");
- while (1)
- {
- x = rand() % row;//用rand函数产生0到row-1之间的随机数
- y = rand() % col;//用rand函数产生0到col-1之间的随机数
- simplealgorithm(board, row, col, &x, &y);
- again:
- if (board[x][y] == ' ')
- {
- board[x][y] = '#';
- break;
- }
- else
- {
- x = rand() % row;
- y = rand() % col;
- goto again;
- }
- }
-
- }
-
- char Win(char board[ROW][COL], int row, int col)
- {
- //返回*,代表玩家胜利,返回#,代表电脑胜利
- // 返回F,代表平局,返回C,代表继续
- //判断行
- for (int i = 0; i < row; i++)
- if (board[i][0] == board[i][1] && board[i][0] == board[i][2] && board[i][0] != ' ')
- return board[i][0];
- //判断列
- for (int i = 0; i < col; i++)
- if (board[0][i] == board[1][i] && board[0][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 (Full(board, ROW, COL))
- return 'F';
- else
- return 'C';
- }
-
- int Full(char board[ROW][COL], int row, int col)
- {
- //检查棋盘是否还有空格
- for(int i = 0; i < row; i++)
- {
- for (int j = 0; j < col; j++)
- {
- if (board[i][j] == ' ')
- {
- return 0;
- }
- }
- }
- return 1;
- }
-
- void simplealgorithm(char board[ROW][COL], int row, int col, int* x, int* y)
- {
- for (int i = 0; i <= row; i++)//行
- {
- if ((board[i][0] == board[i][1] && board[i][0] == '*'))
- {
- *x = i;
- *y = 2;
- }
- else if ((board[i][1] == board[i][2] && board[i][1] == '*'))
- {
- *x = i;
- *y = 0;
- }
- else if ((board[i][0] == board[i][2] && board[i][1] == '*'))
- {
- *x = i;
- *y = 1;
- }
- }
- for (int i = 0; i <= col; i++)//列
- {
- if ((board[0][i] == board[1][i] && board[0][i] == '*'))
- {
- *x = 2;
- *y = i;
- }
- else if ((board[1][i] == board[2][i] && board[1][i] == '*'))
- {
- *x = 0;
- *y = i;
- }
- else if ((board[0][i] == board[2][i] && board[0][i] == '*'))
- {
- *x = 1;
- *y = i;
- }
- }
- for (int i = 0; i <= col; i++)//对角线
- {
- if ((board[i][i] == board[i + 1][i + 1] && board[i][i] == '*'))
- {
- if (i == 0)
- {
- *x = 2;
- *y = 2;
- }
- else if (i == 1)
- {
- *x = 0;
- *y = 0;
- }
- }
- else if ((board[i][2] == board[i + 1][i + 1] && board[i][2] == '*'))
- {
- if (i == 0)
- {
- *x = 2;
- *y = 0;
- }
- else if (i == 1)
- {
- *x = 0;
- *y = 2;
- }
- }
- }
- }

1.其中的Initboard方法对数组进行初始化,博主用了一个memset方法,作用是在一段内存块中填充某个给定的值,第一个参数是要被填充的内存块,这里需要填充的是数组,所以就放入数组名就可以了,第二个参数是被填入的值是什么,这里要初始化为空格,所以填入空格就可以了,第三个参数是需要填充的大小,因为博主是3*3的棋盘,所以就填入ROW*COL就可以了(填入ROW*COL和好处是以后要更改填充的大小,直接改"game.h"中的宏定义即可)
2.其中的Displayboard方法是打印棋盘,大致的效果是下面这样的
3.其中的Player_move方法,我们写这个不仅要程序猿自己能玩,又要让不懂编程的人也能玩 ,所以这里没有用下标为0作为开始,而是从1开始,因为不懂编程的人不知道数组的下标是从0开始的,要考虑其他人的是怎样去下棋的(规定玩家下的棋子是'*')
4.其中的Computer_move方法,就是让电脑下棋,用了一个rand方法去产生一个随机的坐标,而rand方法的使用又要srand的配合 ,srand方法是用来设置rand方法产生一个随机数时的随机数种子,参数seed是整数,所以通常我们用time(NULL)的返回值来作为srand的参数,这样我们就可以得到一个随机数了,但是得到的随机数不是我们想要的(这里大家可以直接去试一试,看看产生的随机数,这里博主就不过多讲解了),所以我们要模上ROW和COL,这样我们就可以得到0-ROW-1之间的整数和0-COL-1之前的整数了。在其中还有一个电脑拦截的方法,就是让电脑阻止玩家,在快要连成一条线的地方去下。(规定电脑下得棋是'#')
5.其中的Win方法就比较简单了,就是去按照三子棋获胜的规则去书写的代码(某一行、某一列、主对角线、次对角线和平局这五种情况)
6.其中的F是用来判断平局的(主要的原理是看棋盘是否还有空格)
这里放了主函数和主函数中game方法的实现
- void game()
- {
- char board[ROW][COL];
- Initboard(board, ROW, COL);
- char ret = '0';
- while (1)
- {
- Player_move(board, ROW, COL);
- Displayboard(board, ROW, COL);
- ret = Win(board, ROW, COL);
- if (ret != 'C')
- {
- break;
- }
- Computer_move(board, ROW, COL);
- Displayboard(board, ROW, COL);
- ret=Win(board, ROW, COL);
- if (ret != 'C')
- {
- break;
- }
- }
- if (ret == '*')
- {
- printf("玩家胜利\n");
- }
- else if (ret == '#')
- {
- printf("电脑胜利\n");
- }
- else
- {
- printf("平局\n");
- }
- }

在这里博主规定了,Win的返回值的具体意义:
'F'代表着平局;'C'代表着继续;'*'代表着玩家胜利;'#'代表着电脑胜利
这是博主做的第一个小游戏,做为小菜鸡的我,在编程的时候遇到了很多麻烦,但是庆幸都一一解决了。博主把自己的方法分享出来,希望大家能对博主进行指正,这样博主才能进步,欢迎大家发表自己的意见。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。