本部分包含数组练习题三子棋。
test.c-三子棋的测试
game.c-三子棋的实现
game.h-三子棋的函数声明
代码部分:
game.h
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 3
#define COL 3
//初始化二维数组
void InitArr(char arr[ROW][COL],int row,int col);
//打印棋盘
void PrintArr(char arr[ROW][COL], int row, int col);
//玩家走
void PlayerMove(char arr[ROW][COL], int row, int col);
//电脑走
void AiMove(char arr[ROW][COL], int row, int col);
//判断输赢
//玩家赢返回--'x'
//电脑赢返回--'o'
//平局返回--'c'
//继续游戏返回--'g'
char isWin(char arr[ROW][COL], int row, int col);
char isFull(char arr[ROW][COL], int row, int col);
game.c
#include"game.h"
//初始化二维数组
void InitArr(char arr[ROW][COL], int row,int col)
{
for (int i = 0;i < row;i++)
{
for (int j = 0;j < col;j++)
{
arr[i][j] = ' ';
}
}
}
//打印棋盘
void PrintArr(char arr[ROW][COL], int row, int col)
{
for (int i = 0;i < row;i++)
{
for (int j = 0;j < col+1;j++)
{
printf("+");
if(j<col)
printf("---");
}
printf("\n");
for (int j = 0;j < col+1;j++)
{
printf("|");
if (j < col )
printf(" %c ", arr[i][j]);
}
printf("\n");
}
for (int j = 0;j < col + 1;j++)
{
printf("+");
if (j < col)
printf("---");
}
printf("\n");
}
//玩家走
void PlayerMove(char arr[ROW][COL], int row, int col)
{
while (1)
{
int x = 0;
int y = 0;
printf("玩家输入:");
scanf("%d %d", &x, &y);
if (x > 0 && x <= ROW && y > 0 && y <= COL)
{
if (arr[x - 1][y - 1] == ' ')
{
arr[x - 1][y - 1] = 'x';
break;
}
else
{
printf("已被占用,请重下\n");
}
}
else
{
printf("下错了,请重下\n");
}
}
}
//电脑走
void AiMove(char arr[ROW][COL], int row, int col)
{
printf("电脑走\n");
while (1)
{
int x = rand() % ROW;
int y = rand() % COL;
if (arr[x][y] == ' ')
{
arr[x][y] = 'o';
break;
}
}
}
//判断输赢
char isWin(char arr[ROW][COL], int row, int col)
{
for (int i = 0;i < row;i++)
{
for (int j = 0;j < col;j++)
{
//一行有三个
if (arr[i][j] == arr[i][j + 1] && arr[i][j + 1] == arr[i][j + 2] && arr[i][j + 1] != ' ')
{
return arr[i][j];
}
//一列有三个
else if (arr[i][j] == arr[i + 1][j] && arr[i + 1][j] == arr[i + 2][j] && arr[i + 1][j] != ' ')
{
return arr[i+1][j];
}
//斜杆有三个
else if (arr[i][j] == arr[i + 1][j + 1] && arr[i + 1][j + 1] == arr[i + 2][j + 2] && arr[i + 1][j + 1] != ' ')
{
return arr[i+1][j+1];
}
else if (arr[i][j] == arr[i - 1][j - 1] && arr[i - 1][j - 1] == arr[i - 2][j - 2] && arr[i - 1][j - 1] != ' ')
{
return arr[i-1][j-1];
}
}
}
//平局
return isFull(arr, ROW, COL);
}
char isFull(char arr[ROW][COL], int row, int col)
{
for (int i = 0;i < row;i++)
{
for (int j = 0;j < col;j++)
{
if (arr[i][j] == ' ')
return 'g';
}
}
return 'c';
}
test.c
#include"game.h"
void menu()
{
printf("*********************\n");
printf("**** 1.开始游戏 ****\n");
printf("**** 0.退出游戏 ****\n");
printf("*********************\n");
}
void game()
{
//创建二维数组
char arr[ROW][COL];
//初始化二维数组
InitArr(arr,ROW,COL);
//打印棋盘
PrintArr(arr,ROW,COL);
char ret = 0;
while (1)
{
//玩家走
PlayerMove(arr, ROW, COL);
PrintArr(arr, ROW, COL);
ret=isWin(arr, ROW, COL);
if (ret != 'g')
break;
//电脑走
AiMove(arr, ROW, COL);
PrintArr(arr, ROW, COL);
ret=isWin(arr, ROW, COL);
if (ret != 'g')
break;
}
if (ret == 'x')
printf("玩家胜利\n");
else if (ret == 'o')
printf("电脑胜利\n");
else if (ret == 'c')
printf("平局\n");
}
int main()
{
//数组练习题
//三子棋
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请输入>");
scanf("%d", &input);
switch (input)
{
case 1:
printf("三子棋游戏开始:\n");
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入无效,请重新输入\n");
break;
}
} while (input);
}
笔记:
- 数组
- 5.1 概述
- 所谓数组,就是一个集合,里面存放了相同类型的数据元素
- 特点1:数组中的每个数据元素都是相同的数据类型
- 特点2:数组是由连续的内存位置组成的
- 例图:
- 5.2 一维数组
- 5.2.1 一维数组定义方式
- 一维数组定义的三种方式:
- 数据类型 数组名[ 数组长度 ];
- 数据类型 数组名[ 数组长度 ] = { 值1,值2 ...};
- 数据类型 数组名[ ] = { 值1,值2 ...};
- 图示:
- 注意:如果在初始化数据的时候,没有全部填写完,会用0来填补剩余数据+数组长度必须是常量
- 总结1:数组名的命名规范与变量名命名规范一致,不要和变量重名
- 总结2:数组中下标是从0开始索引
- 一维数组定义的三种方式:
- 5.2.2 一维数组数组名
- 一维数组名称的用途:
- 1.可以统计整个数组在内存中的长度
- 2.可以获取数组在内存中的首地址
- 注意:数组名是常量,因此不可以赋值
- 总结1:直接打印数组名,可以查看数组所占内存的首地址
- 总结2:对数组名进行sizeof,可以获取整个数组占内存空间的大小
- 一维数组名称的用途:
- 5.2.3 冒泡排序
- 作用: 最常用的排序算法,对数组内元素进行排序
- 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
- 对每一对相邻元素做同样的工作,执行完毕后,找到第一个最大值。
- 重复以上的步骤,每次比较次数-1,直到不需要比较
- 作用: 最常用的排序算法,对数组内元素进行排序
- 5.2.1 一维数组定义方式
- 5.3 二维数组
- 二维数组就是在一维数组上,多加一个维度。
- 5.3.1 二维数组定义方式
- 二维数组定义的四种方式:
- 数据类型 数组名[ 行数 ][ 列数 ];
- 数据类型 数组名[ 行数 ][ 列数 ] = { {数据1,数据2 } ,{数据3,数据4 } };
- 数据类型 数组名[ 行数 ][ 列数 ] = { 数据1,数据2,数据3,数据4};
- 数据类型 数组名[ ][ 列数 ] = { 数据1,数据2,数据3,数据4};
- 建议:以上4种定义方式,利用第二种更加直观,提高代码的可读性
- 总结:在定义二维数组时,如果初始化了数据,可以省略行数
- 二维数组定义的四种方式:
- 5.3.2 二维数组数组名
- 二维数组名称的用途:
- 1.查看二维数组所占内存空间
- 2.获取二维数组首地址
- 二维数组名称的用途:
- 5.4 数组&函数
- 传递数组给函数
- 可以通过指定不带下标(索引)的数组名来传递一个指向数组的指针
- 传数组给一个函数,数组类型自动转换为指针类型,因而传的实际是地址
- 数组作为参数的三种方式
- 1.形式参数是一个指针:void myFunction(int *param)
- 2.形式参数是一个已定义大小的数组:void myFunction(int param[10])
- 3.形式参数是一个未定义大小的数组:void myFunction(int param[])
- 从函数返回数组
- C++ 不允许返回一个完整的数组作为函数的参数。但是,您可以通过指定不带索引的数组名来返回一个指向数组的指针。
- 如果您想要从函数返回一个一维数组,您必须声明一个返回指针的函数。
- 例子:int * myFunction()
- 传递数组给函数
- 5.1 概述