- 三子棋游戏
- 冒泡排序
创建一个新的文件。
首先分析:我们想要实现一个三子棋的游戏,先构建一个大概的框架,还要有一个选择的菜单,而这个菜单界面一开始就要出现。可见这里可以用do while循环语句实现,其次假设我们输入1为进入游戏,输入0为退出游戏,输入其他数字表示选择错误,我们可以使用switch case语句实现分支选择。可以这样写:
#includevoid menu() { printf("************************n"); printf("******* 1.paly *********n"); printf("******* 0.exit *********n"); printf("************************n"); } int main() { int input = 0; do { menu(); printf("请选择:>"); scanf("%d", &input); switch (input) { case 1: printf("三子棋n"); break; case 0: printf("退出游戏n"); break; default: printf("选择错误n"); } } while (input); return 0; }
代码实现效果为:
其次分析:当我们选择1进入游戏之后,如下图所示,当我们要下棋的时候,首先得有一个棋盘存放数据,让玩家先输入坐标下棋,电脑后下棋,那么玩家和电脑下的棋都是要存起来。九宫格的话就要创建一个3*3的二维数组来存放数据。实现下棋的功能,我们必须要打印一个棋盘,其次玩家要下棋,然后电脑也要下棋,到最后也需要判断输赢的功能。
再分析:生成的棋盘在我们还没下棋的时候,是不是里面没有放东西呢?当然不是,里面放的是空格,所以在一开始二维数组里面打印的是空格,放出来的棋盘给了一种里面没有东西的假象。所以首先写一个初始化棋盘的函数,棋盘里面放的是空格,注意函数的声明。
void InitBoard(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++)
{
board[i][j] = ' ';//初始化棋盘
}
}
}
打印棋盘的分析:我们来看一下初始化的棋盘对不对需要打印棋盘,而每下一颗棋也需要显示出来,所以都需要打印棋盘出来。所以也要创建一个打印棋盘的函数。要创建一个这样得棋盘,如下图的棋盘,我们可以把它看成一行一行为一组。每一行也可以分成输入和打印分割行。每一组每一列也可以看到数据部分是空格加竖杠,竖杠是列数减一,分割部分也是一样的道理。
//打印棋盘
void DispalyBorad(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");
}
}
}
实现效果:
玩家下棋分析:棋盘出来之后,要完成下棋的动作,让玩家输入坐标下棋,然后电脑再下棋,这样就是要写一个循环把这样两个重复的动作放在里面,然后判断输赢。玩家下棋,就是要输入坐标啊,但是数组下标是从0开始的,但是玩家写坐标的时候不会从(0,0)的坐标开始写,所以要求玩家只能输入横纵坐标分别是1-3。不能超出坐标的范围所以我们可以写一个分支语句。而玩家下棋这个动作不只有一次,所以要写一个循环。在棋盘内还需要判断是否空格被占用。
//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("玩家下棋:>n");
printf("请输入坐标:>");
scanf("%d %d", &x, &y);
while (1)
{
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");
}
}
}
代码实现效果:
电脑下棋分析:弄简单一点,我们找没有下棋的空格随机下。在这个数组的范围内,我们调用rand函数随机生成坐标。用rand()%row的范围就是0~2,rand()%col也是0-2。当生成的坐标是空格的话,电脑就下棋。
函数代码如下:
void ComputerMove(char board[ROW][COL], int row, int col)
{
printf("电脑下棋:>n");
int x = 0;
int y = 0;
x = rand() % row;
y = rand() % col;
while (1)
{
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
实现效果:
判断输赢:当玩家或者电脑下棋的话,形成一行、一列或者对角线连成三子的话,游戏中的一方就赢了,当九个格子都被占满还没有分出胜负,就打成平局,而还没有这三种情况的时候,游戏则要继续下去。
四种情况我们来约定一下:
//玩家赢 - '*'
//电脑赢 - '#'
//平局 - 'Q'
//继续游戏-'C'
//判断输赢
char Iswin(char board[ROW][COL], int row, int col)
{
//行
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
{
return board[i][1];
}
}
//列
for (j = 0; j < col; j++)
{
if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' ')
{
return board[j][1];
}
}
//对角线
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';//继续
}
完整代码如下:
game.h
#include#include #include #define ROW 3//行 #define COL 3//列 //初始化函数声明 void InitBoard(char board[ROW][COL], int row, int col); //打印棋盘函数 void DispalyBorad(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;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';//初始化棋盘
}
}
}
//打印棋盘
void DispalyBorad(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");
printf("请输入坐标:>");
scanf("%d %d", &x, &y);
while (1)
{
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;
x = rand() % row;
y = rand() % col;
while (1)
{
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
//判断棋盘是否满了
//满了返回1
//不满返回0
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;
}
}
}
}
//玩家赢 - '*'
//电脑赢 - '#'
//平局 - 'Q'
//继续游戏-'C'
//判断输赢
char Iswin(char board[ROW][COL], int row, int col)
{
//行
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
{
return board[i][1];
}
}
//列
for (j = 0; j < col; j++)
{
if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' ')
{
return board[j][1];
}
}
//对角线
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';
}
test.c
#include "game.h"
void menu()
{
printf("************************n");
printf("******* 1.paly *********n");
printf("******* 0.exit *********n");
printf("************************n");
}
void game()
{
char ret = 0;
char board[ROW][COL] = { 0 };
//初始化棋盘功能
InitBoard(board,ROW,COL);
//打印棋盘
DispalyBorad(board, ROW, COL);
while (1)
{
//玩家下棋
PlayerMove(board, ROW, COL);
//判断输赢
ret=Iswin(board, ROW, COL);
if (ret != 'C')
{
break;
}
DispalyBorad(board, ROW, COL);
//电脑下棋
ComputerMove(board, ROW, COL);
//判断输赢
ret=Iswin(board, ROW, COL);
if (ret != 'C')
{
break;
}
DispalyBorad(board, ROW, COL);
}
if (ret == '*')
{
printf("玩家赢n");
}
else if (ret == '#')
{
printf("电脑赢n");
}
else
{
printf("平局n");
}
DispalyBorad(board, ROW, COL);
}
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");
}
} while (input);
return 0;
}
冒泡排序
冒泡排序的核心思想是把两个相邻元素进行比较。我们通过一个例子来讲解以下冒泡排序。
例:实现一个对整形数组的冒泡排序
解析:假设一个整型数组arr为9,8,7,6,5,4,3,2,1,0实现升序排列。如下图,写一个函数,我们要传给函数的参数就是数组首元素的地址。冒泡排序就是把两个相邻元素相比较,我们要实现升序排列,就是把9到0,一个一个元素相邻之间进行比较。那这里要排序多少趟呢?i 个元素就要排序 sz-1 趟。用for循环实现趟数。
每次交换元素的次数也会改变,第一趟排序将9交换到0的位置,需要交换的次数为9次,第二趟交换8到1的位置8次,可以看到每次交换的次数都会减少一次。所以令 j 为每个元素要交换的次数,那每次也要写一个for循环,当 j 小于 sz-1-i 次。
判断部分当arr[j]大于arr[j+1]时就相互交换。
代码如下:
#includevoid bubble_sort(int arr[],int sz) { //确定趟数 int i = 0; for (i = 0; i < sz - 1; i++) { //一趟冒泡排序 int j = 0; for (j =0; j if (arr[j] > arr[j + 1]) { //交换 int tmp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = tmp; } } } } int main() { //数组进行升序排序 int arr[] = { 9,8,7,6,5,4,3,2,1,0 }; int sz = sizeof(arr) / sizeof(arr[0]); bubble_sort(arr,sz); int i = 0; for (i = 0; i < sz; i++) { printf("%d ", arr[i]); } return 0; }
代码实现效果:
写在最后:托更了好久,往后尽量一个星期更一篇吧。码字不易,如果对你有帮助的话,给个三连或者关注一下吧,感谢支持!



