在我们学习了c语言到一定程度的时候,是不是有想过学的这些除了刷题还能干嘛呢?当然,现在是互联网信息特别发达,我见过比较多的都是会对游戏有一定的兴趣吧!我们一般情况下呢都是玩的别人开发出来的游戏,那我们有没有想过有一天我们能自己开发一些通过自己编程写出来的一些小游戏呢?相比如果你能自己写出来肯定会觉得自己有那么一点小小的成就感,哈哈哈哈哈,不错,我就是学会了忍不住想要跟大家分享一下这些小游戏。
这个游戏实现其实比较简单的,只要你对循环了解清楚了就能上手的。
首先呢我们先制作一个类似如下代码的一个游戏菜单:
实现代码是:
void menu() {
printf("******************\n");
printf("**1.play 0.exit**\n");
printf("******************\n");
}
因为当你一运行的时候就需要弹出这个菜单,所以我们这里在main函数中调用我们的菜单函数menu(),除了菜单我们就需要在通过玩家的选择来确定是玩游戏还是退出游戏,所以我们这里要用到switch,通过输入一个数选择对应的下一步操作,而这个操作过程不会说只玩一次,所以我们用到一个循环,即do while 语句,因为你一进入菜单就需要进行一个选择。
实现的效果是:
实现代码如下:
int main() {
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择>:\n");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
return 0;
}
而接下来就是对游戏内容的实现,我们这里呢做一个1到100的猜数字游戏,不会太难。而在上述代码中,我们看到了一个srand((unsigned int)time(NULL));是不是感觉到有点陌生,没关系,要实现我们这个游戏呢需要用到一个随机数,而为了能得到一个随机数,我们这里想到了一个时间戳来作为达到生成随机数的目的
这是rand生成随机数的一个用法
先来看一下我们想要实现的一个效果,游戏的过程
达到这样的一个效果,就是你猜一个数字之后,它会提示你所要猜的数字和你输入的数字的一个大小比较从而达到一个缩小范围的效果,进而增大猜中的几率。
游戏内容的实现代码如下:
void game() {
int ret = 0;
int guess = 0;
ret = rand() % 100 + 1;
while (1) {
printf("请猜数字:>");
scanf("%d", &guess);
if (guess > ret) {
printf("猜大了\n");
}
else if (guess<ret) {
printf("猜小了\n");
}
else
{
printf("恭喜你,猜对了!\n");
break;
}
}
与上一个游戏一样,从菜单函数开始写起。
选择0是退出,选择1是开始玩游戏。
这里面我创建了两个.c文件(test.c和game.c),一个.h头文件(game.h)用来声明需要用到的函数
。
1.先创建一个3*3的二维数组用来存放数据;
2.然后我们先从棋盘开始分析,棋盘要实现跟上述效果一样我们可以分析,先对棋盘初始化,给二维数组每一个元素置为空格,目的是把位置占着,然后等后面需要下棋的时候在用其他的棋子来替换;
3.棋盘初始化成功之后,我们就需要对棋手的操作进行函数实现了,我们专门通过一个玩家下棋的一个函数来进行实现,玩家下棋之后打印棋盘;
4.玩家函数实现成功后,我们对电脑下棋也实现一个函数,这个电脑下棋的函数我们再次用到了随机数rand的使用,目的是让电脑随机生成一个棋盘上的坐标(有效坐标),然后将棋子下在指定位置,然后再次打印棋盘;
5.最后一步就是玩家和电脑下棋终有一次要有几种情况来判断输赢,所以我们最后在实现一个判断输赢的函数
test.c
#include"game.h"
void game()
{
//需要一个3*3的二维数组存放数据
char board[3][3] = { 0 };
//初始化棋盘
InitBoard(board,ROW,COL);
//打印棋盘
DisplayBoard(board, ROW, COL);
char ret = 0;
while (1)
{
//玩家下棋
PlayerMove(board, ROW, COL);
// 打印棋盘
DisplayBoard(board, ROW, COL);
// 判断输赢
ret = IsWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
//电脑下棋
ComputerMove(board, ROW, COL);
//打印棋盘
DisplayBoard(board, ROW, COL);
//判断输赢
IsWin(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 menu()
{
printf("**************************\n");
printf("********* 1.play *********\n");
printf("********* 0.exit *********\n");
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("退出游戏!");
break;
default:
printf("选择错误,请重新输入!");
break;
}
} while (input);
return 0;
}
game.h
#include
#include
#include
#include
#define ROW 3
#define COL 3
//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col);
//打印棋盘
void DisplayBoard(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] = ' ';
}
}
//memset(&board[0][0], " ", row * col * sizeof(board[0][0]));
}
void DisplayBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 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)
{
int j = 0;
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);
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)
{
int x = 0;
int y = 0;
printf("电脑下棋:>\n");
while (1)
{
x = rand() % 3;
y = rand() % 3;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
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][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[1][i] != ' ')
{
return board[1][i];
}
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
{
return board[0][0];
}
if (board[0][2] == board[1][1] && board[2][0] == board[1][1] && board[1][1] != ' ')
{
return board[1][1];
}
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return 'C';
}
}
}
return 'Q';
}
三子棋游戏就实现了
扫雷想必大家肯定都知道怎么玩的吧,那么应该对游戏规则肯定不陌生,这里前面的写法我们与上述的三子棋都有一点类似,就是游戏规则实现不同
实现的效果:
1.这个游戏我们也是先从布置棋盘开始,我们这里创建了两个1111的棋盘,一个棋盘是用来排雷用的,一个是用来埋雷用的,其中99的坐标有效,外围多出来的位置用来显示坐标,方便玩家找到需要排雷的指定位。
2.我们这里也要有初始化排雷棋盘的函数,还有初始化埋雷棋盘的函数
3.还需要一个打印棋盘的函数,每排查一次都需要打印一次棋盘,然后如果玩家排到雷了那么把埋雷的棋盘打印给他看,让他知道那些地方埋雷了
4.最后还需要一个布置雷的函数,我们这里又是需要用到随机数,所以有需要用到rand,前面已经把用法给大家找出来了,就不细说了。
代码安排:
test.c
#include"game.h"
void menu()
{
printf("**************************\n");
printf("******* 0.退出游戏 *******\n");
printf("******* 1.扫雷游戏 *******\n");
printf("**************************\n");
}
void game()
{
//建立两个数组分别存放数据
char mine[ROWS][COLS] = { 0 };//用来存放布置雷的信息的数组
char show[ROWS][COLS] = { 0 };//用来存放排查雷的信息的数组
//初始化排查雷的棋盘
InitBoard(mine, ROWS, COLS,'0');
//初始化布置雷的棋盘
InitBoard(show, ROWS, COLS, '*');
//打印棋盘
PrintBoard(show, ROW, COL);
//布置雷
SetMine(mine, ROW, COL);
PrintBoard(mine, ROW, COL);
//排雷
RemoveMine(mine,show,ROW,COL);
}
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 0:
printf("退出游戏!\n");
break;
case 1:
game();
break;
default:
printf("选择错误,请重新输入!\n");
}
}while (input);
return 0;
}
game.h
#include
#include
#include
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define EASY_COUNT 10
//初始化排雷界面
void InitBoard(char arr[ROWS][COLS], int rows, int cols,char set);
//打印棋盘
void PrintBoard(char arr[ROWS][COLS], int row, int col);
//布置雷
void SetMine(char arr[ROWS][COLS], int row, int col);
//排查雷
void RemoveMine(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col);
game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void InitBoard(char arr[ROWS][COLS], int rows, int cols,char set)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
int j = 0;
for (j = 0; j < cols; j++)
{
arr[i][j] = set;
}
}
}
void PrintBoard(char arr[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("******* 排雷 *******\n");
for (i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", arr[i][j]);
}
printf("\n");
}
}
void SetMine(char arr[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (arr[x][y] == '0')
{
arr[x][y] = '1';
count--;
}
}
}
//统计雷的个数
int MineCount(char mine[ROWS][COLS], int x, int y)
{
return (mine[x - 1][y - 1] + mine[x - 1][y] +
mine[x - 1][y + 1] + mine[x][y - 1] +
mine[x + 1][y - 1] + mine[x + 1][y] +
mine[x + 1][y + 1] + mine[x][y + 1] - 8 * '0');
}
void RemoveMine(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int safe = 0;
while (safe<row*col-EASY_COUNT)
{
printf("请输入你要排查的坐标:>");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (show[x][y] == '*')
{
if (mine[x][y] == '1')
{
printf("很遗憾,你被炸死\n");
PrintBoard(mine, ROW, COL);
break;
}
else
{
//如果该坐标不是雷,就要统计该坐标周围有几个雷
int count = MineCount(mine, x, y);
show[x][y] = count + '0';
PrintBoard(show, ROW, COL);
safe++;
}
}
else
{
printf("该坐标已经排查,请重新输入!\n");
}
}
else
{
printf("你输入的坐标非法,请重新输入!\n");
}
}
}
经过上面三个游戏的实现方式,我们发现了有很多的现实性,所以我在了解了每个游戏怎么写的前提下,把上述三个游戏整合到一个项目里面,然后把三个游戏分别放到菜单里面去。
好了,直接安排代码:
test.c
#include
#include"game2.h"
#include"game3.h"
void menu()
{
printf("**************************\n");
printf("******* 1.猜数字 *******\n");
printf("******* 2.三子棋 *******\n");
printf("******* 3.扫雷 *******\n");
printf("******* 0.退出游戏 *******\n");
printf("**************************\n");
}
void game1()
{
int num = 0;
int ret = rand() % 100 + 1;//得到一个1-100的随机数
while (1)
{
printf("请猜该数字:>");
scanf("%d", &num);
if (num > ret)
{
printf("猜大了!\n");
}
else if (num < ret)
{
printf("猜小了!\n");
}
else
{
printf("恭喜你!猜对了!\n");
break;
}
}
}
void game2()
{
//需要一个3*3的二维数组存放数据
char board[3][3] = { 0 };
//初始化棋盘
initBoard(board,Row,Col);
//打印棋盘
DisplayBoard(board, Row, Col);
char ret = 0;
while (1)
{
//玩家下棋
PlayerMove(board, Row, Col);
// 打印棋盘
DisplayBoard(board, Row, Col);
// 判断输赢
ret = IsWin(board, Row, Col);
if (ret != 'C')
{
break;
}
//电脑下棋
ComputerMove(board, Row, Col);
//打印棋盘
DisplayBoard(board, Row, Col);
//判断输赢
IsWin(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 game3()
{
//建立两个数组分别存放数据
char mine[ROWS][COLS] = { 0 };//用来存放布置雷的信息的数组
char show[ROWS][COLS] = { 0 };//用来存放排查雷的信息的数组
//初始化排查雷的棋盘
InitBoard(mine, ROWS, COLS, '0');
//初始化布置雷的棋盘
InitBoard(show, ROWS, COLS, '*');
//打印棋盘
PrintBoard(show, ROW, COL);
//布置雷
SetMine(mine, ROW, COL);
PrintBoard(mine, ROW, COL);
//排雷
RemoveMine(mine, show, ROW, COL);
}
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 0:
printf("退出游戏!\n");
break;
case 1:
game1();
break;
case 2:
game2();
break;
case 3:
game3();
default:
printf("选择错误,请重新输入!\n");
}
} while (input);
return 0;
}
game2.h
#include
#include
#include
#include
#define Row 3
#define Col 3
//初始化棋盘
void initBoard(char board[Row][Col], int row, int col);
//打印棋盘
void DisplayBoard(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);
game3.h
#include
#include
#include
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define EASY_COUNT 10
//初始化排雷界面
void InitBoard(char arr[ROWS][COLS], int rows, int cols, char set);
//打印棋盘
void PrintBoard(char arr[ROWS][COLS], int row, int col);
//布置雷
void SetMine(char arr[ROWS][COLS], int row, int col);
//排查雷
void RemoveMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
game2.c
#include"game2.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] = ' ';
}
}
//memset(&board[0][0], " ", row * col * sizeof(board[0][0]));
}
void DisplayBoard(char board[Row][Col], int row, int col)
{
int i = 0;
int j = 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)
{
int j = 0;
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);
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)
{
int x = 0;
int y = 0;
printf("电脑下棋:>\n");
while (1)
{
x = rand() % 3;
y = rand() % 3;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
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][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[1][i] != ' ')
{
return board[1][i];
}
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
{
return board[0][0];
}
if (board[0][2] == board[1][1] && board[2][0] == board[1][1] && board[1][1] != ' ')
{
return board[1][1];
}
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return 'C';
}
}
}
return 'Q';
}
game3.c
#include"game3.h"
void InitBoard(char arr[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
int j = 0;
for (j = 0; j < cols; j++)
{
arr[i][j] = set;
}
}
}
void PrintBoard(char arr[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("******* 排雷 *******\n");
for (i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", arr[i][j]);
}
printf("\n");
}
}
void SetMine(char arr[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (arr[x][y] == '0')
{
arr[x][y] = '1';
count--;
}
}
}
//统计雷的个数
int MineCount(char mine[ROWS][COLS], int x, int y)
{
return (mine[x - 1][y - 1] + mine[x - 1][y] +
mine[x - 1][y + 1] + mine[x][y - 1] +
mine[x + 1][y - 1] + mine[x + 1][y] +
mine[x + 1][y + 1] + mine[x][y + 1] - 8 * '0');
}
void RemoveMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int safe = 0;
while (safe < row * col - EASY_COUNT)
{
printf("请输入你要排查的坐标:>");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (show[x][y] == '*')
{
if (mine[x][y] == '1')
{
printf("很遗憾,你被炸死\n");
PrintBoard(mine, ROW, COL);
break;
}
else
{
//如果该坐标不是雷,就要统计该坐标周围有几个雷
int count = MineCount(mine, x, y);
show[x][y] = count + '0';
PrintBoard(show, ROW, COL);
safe++;
}
}
else
{
printf("该坐标已经排查,请重新输入!\n");
}
}
else
{
printf("你输入的坐标非法,请重新输入!\n");
}
}
}
好了,今日小白的分享就到这了,其实这些游戏的代码有些地方的功能还可以进行优化,比如扫雷那个地方,还是有些不足的,如果大家兴趣的话可以跟进哦。