学了这么长时间的C语言,你是否觉得没有一个没写过稍微长点的代码显得很没有成就感!不怕,今天带你做一个小游戏,领略一下写C和小游戏的快乐。写完记得给自己一个鼓励哦!
一、三子棋小游戏
想必大家都玩过三子棋小游戏,只有先了解规则,我们才能写出对应的算法。
1、首先需要思考的事情
斗棋首先得有一个平台,比如三子棋的平台就是我们常见的九宫格 如下图:
这时候有人就会说了,这谁都知道,可是这个图形怎么在电脑上显示呢?
问得好
我们把这个图案画出来(小声哔哔:个人感觉画的还不错)从图中可以看出蓝色分为三层,红色其实也分为三层,只不过最后一层没有省略了。
代码如下:
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");
}
}
2、开始下棋
平台我们已经做好了,第二步我们该干嘛呢?
肯定是可以下棋啦!
那么问题来了,我们怎么将我们的棋子下到对应的位置呢?而且还不能重复?
三子棋是一个双人游戏,那我们就写一个人机对打的操作!
玩家操作函数封装为
void PlayerMove(char board[ROW][COL], int row, int col)
电脑玩家操作函数封装为
void ComputerMove(char board[ROW][COL], int row, int col)
看表面都能看出来两个函数其实没有太大区别。
注意:我们把下棋的位置看成一个个二维数组的元素,其实就显而易见了,我们下的棋子就是给相应二维数组元素赋值,这里我们把玩家下的棋用 ∗ \color{black}{*} ∗ 表示,电脑玩家下的棋用 # 表示。
那我们该如何实现这两个函数呢?
代码如下:
void PlayerMove(char board[ROW][COL], int row, int col)
{
printf("玩家走>\n");
int x = 0;
int y = 0;
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)
{
printf("电脑走>\n");
int x = 0;
int y = 0;
while (1)
{
x = rand() % row; // 将棋子位置合法化, 下同
y = rand() % col;
if (board[x][y] == ' ') // 当前位置为空 则电脑下棋
{
board[x][y] = '#';
break;
}
}
}
3.判断输赢
当玩家下完棋之后是不是要判断一下当前是否已经赢了。
我们该如何判断输赢呢?
这时我们自己定义一个规则:
- 首先定义一个变量 ret
- 让 ret 来返回当前局面是否已经成立或是平局
- 当玩家赢返回 ∗ \color{black}{*} ∗
- 当电脑玩家赢返回 #
- 平局返回Q
- 继续游戏时返回 C
代码如下:
int IsFull(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][j] == ' ') // 如果还有空位置说明还没结束
return 0;
}
}
return 1;
}
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];
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 (IsFull(board, row, col)) // 平局
{
return 'Q';
}
return 'C'; // 以上都不满足则继续游戏
}
4.代码实现
我们理解完较难代码的实现之后,下面开始真正做一个完整的小游戏吧!
1、首先我们写一个有文件说明一下几个重要函数
game.h代码如下:
#pragma once
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#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);
2、主函数代码主要调用函数用途
main.c代码如下:
#include "game.h"
void menu()
{
printf("****************************\n");
printf("********** 1.paly **********\n");
printf("********** 0.exit **********\n");
printf("****************************\n");
}
void game()
{
char board[ROW][COL];
InitBoard(board, ROW, COL);
DisplayBoard(board, ROW, COL);
char ret;
while (1)
{
PlayerMove(board, ROW, COL); // 玩家下棋
DisplayBoard(board, ROW, COL); // 打印棋盘
ret = IsWin(board, ROW, COL); // 返回标志代码 ‘C’为继续 ‘Q’为平局 ‘*’为玩家赢 ‘#’为电脑赢
if (ret != 'C')
break;
ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ret = IsWin(board, ROW, COL);
if (ret != 'C')
break;
}
if (ret == '*')
printf("玩家赢!\n");
if (ret == '#')
printf("电脑赢!\n");
if (ret == 'Q')
printf("平局!\n");
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
menu();
do
{
printf("请选择>");
scanf("%d", &input);
switch (input)
{
case 1: game(); break;
case 0: printf("退出游戏!\n"); break;
default: printf("选择错误!\n"); break;
}
} while (input);
}
3、下面代码才是函数的实现也是游戏的核心内容
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 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 PlayerMove(char board[ROW][COL], int row, int col)
{
printf("玩家走>\n");
int x = 0;
int y = 0;
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)
{
printf("电脑走>\n");
int x = 0;
int y = 0;
while (1)
{
x = rand() % row; // 将棋子位置合法化, 下同
y = rand() % col;
if (board[x][y] == ' ') // 当前位置为空 则电脑下棋
{
board[x][y] = '#';
break;
}
}
}
int IsFull(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][j] == ' ')
return 0;
}
}
return 1;
}
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];
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 (IsFull(board, row, col))
{
return 'Q';
}
return 'C';
}