# 软件实现

## 重要绘制图形函数介绍

### 绘制按钮函数

void DrawButton(int x, int y, int width, int height, u8* Text, char sta)
{
int iLen = strlen((char*)Text);

if (x > 239 || x < 0 || y < 0 || y > 319) return;

POINT_COLOR = WHITE;
LCD_DrawRectangle(x, y, x+width, y+height);
if (sta==1)
{
LCD_Fill(x+1, y+1, x+width-1, y+height-1, BLUE);
BACK_COLOR = BLUE;
Show_Str(x+((width-iLen*8)/2), y+((height-16)/2), 200, 16, Text, 16, 0);
}
else if(sta==0)
{
LCD_Fill(x+1, y+1, x+width-1, y+height-1, GRAY);
BACK_COLOR = GRAY;
Show_Str(x+((width-iLen*8)/2)+2, y+((height-16)/2)+2, 200, 16, Text, 16, 0);
}
else if(sta==2)
{
LCD_Fill(x+1, y+1, x+width-1, y+height-1, GREEN );
BACK_COLOR = GREEN ;
Show_Str(x+((width-iLen*8)/2)+2, y+((height-16)/2)+2, 200, 16, Text, 16, 0);
}
}


sta=1sta=2sta=0

### 绘制棋子函数

void DrawChess(int x, int y, int num, char sta)
{
uint16_t ChessColor;
uint16_t xChess;
uint16_t yChess;

if (x>15 || x<0 || y>15 || y<0)return; //超范围了
//判断是下棋还是复盘
if (sta)
{
if (g_Chess[x][y]!=0)return;   //已有棋子
}

//判断棋子颜色
(num%2==0) ? (ChessColor=BLACK) : (ChessColor=WHITE);

//计算棋子坐标
xChess = CHESSBOARD_START_X + (x*CHESSGRID_SIZE);
yChess = CHESSBOARD_START_Y + (y*CHESSGRID_SIZE);

LcdDrawCircleA(xChess,
yChess,
CHESSGRID_SIZE/2-1,
ChessColor,
1);
if(voice==1)          //判断灯光是否打开 若打开 每次下子蜂鸣器响100ms
{
LED0=0;
delay_ms(100);
LED0=1;
}
delay_ms(10);
if (sta == 0) return;
g_ChessNum++;
g_Chess[x][y] = g_ChessNum;
}


### 绘制棋盘界面函数

void DrawChessBoard(void)
{
int i;
//填充棋盘背景色
LCD_Fill(CHESSBOARD_START_X-5, CHESSBOARD_START_Y-5,
CHESSBOARD_END_X+5, CHESSBOARD_END_Y+5, CHESSBOARD_COLOR);
POINT_COLOR = BLACK;
//绘制边框线
LCD_DrawRectangle(CHESSBOARD_START_X-3, CHESSBOARD_START_Y-3,
CHESSBOARD_END_X+3, CHESSBOARD_END_Y+3);
LCD_DrawRectangle(CHESSBOARD_START_X-4, CHESSBOARD_START_Y-4,
CHESSBOARD_END_X+4, CHESSBOARD_END_Y+4);
LCD_DrawRectangle(CHESSBOARD_START_X, CHESSBOARD_START_Y,
CHESSBOARD_END_X, CHESSBOARD_END_Y);

POINT_COLOR = BLACK;
//绘制垂直线
for (i = 1; i < 15; i++)
{
LCD_DrawLine(CHESSBOARD_START_X,
CHESSBOARD_START_Y + (CHESSGRID_SIZE*i),
CHESSBOARD_END_X,
CHESSBOARD_START_Y + (CHESSGRID_SIZE*i));
}

//绘制水平线
for (i = 1; i < 15; i++)
{
LCD_DrawLine(CHESSBOARD_START_X + (CHESSGRID_SIZE*i),
CHESSBOARD_START_Y,
CHESSBOARD_START_X + (CHESSGRID_SIZE*i),
CHESSBOARD_END_Y);
}
DrawButton(5, 285, 80, 25, (u8*)"重新开始", 1);
DrawButton(87, 285, 48, 25, (u8*)"悔棋", 1);
DrawButton(137, 285, 48, 25, (u8*)"帮助", 1);
DrawButton(187, 285, 49, 25, (u8*)"返回", 1);
}


## 重要界面函数介绍

### 模式选择界面

void Main(void)//主界面函数
{
LCD_Clear(GBLUE);
BACK_COLOR = GBLUE;
POINT_COLOR = RED;
Show_Str((240 - 24*3)/2, 30, 200, 24, (u8*)"五子棋", 24, 0);
//创建按钮
DrawButton(40, 100, 160, 40, (u8*)"人机对战", 1);
DrawButton(40, 150, 160, 40, (u8*)"双人对战", 1);
DrawButton(40, 200, 160, 40, (u8*)"游戏介绍", 1);
DrawButton(40, 250, 160, 40, (u8*)"设置", 1);
}


### 对战界面

void One(void)
{
LCD_Clear(BRRED);
POINT_COLOR = WHITE;
DrawChessBoard();
BACK_COLOR = BRRED;
POINT_COLOR=BLACK;
Show_Str(34, 10, 240, 34, (u8*)"五子棋人机对战", 24, 0);
One_test();
}


### 设置界面

void Setting(void)
{
POINT_COLOR = WHITE;
//绘制关于窗口
LCD_DrawRectangle(20, 110, 220, 220);
LCD_DrawRectangle(21, 111, 219, 219);
LCD_Fill(22, 112, 218, 218, BLACK);
BACK_COLOR = BLACK;
Show_Str(104, 115, 32, 16, (u8*)"设置", 16, 0);
Show_Str(40, 140, 136, 16, (u8*)"灯光", 16, 0);
Show_Str(40, 165, 136, 16, (u8*)"关于", 16, 0);
//绘制按钮
DrawButton(150, 140, 25, 20, (u8*)"开", 2);
DrawButton(175, 140, 25, 20, (u8*)"关", 0);
DrawButton(150, 165, 50, 20, (u8*)"打开", 2);
DrawButton(90, 195, 60, 20, (u8*)"返回", 1);
Set_test();
}


### 关于界面

void About(void)
{
POINT_COLOR = WHITE;
//绘制关于窗口
LCD_DrawRectangle(20, 110, 220, 220);
LCD_DrawRectangle(21, 111, 219, 219);
LCD_Fill(22, 112, 218, 218, BLACK);
BACK_COLOR = BLACK;
//文本
Show_Str(104, 115, 32, 16, (u8*)"关于", 16, 0);
Show_Str(40, 135, 136, 16, (u8*)"平台:STM32F103精英版", 16, 0);
Show_Str(40, 155, 136, 16, (u8*)"作者:YWL", 16, 0);
Show_Str(40, 175, 136, 16, (u8*)"时间:2019-11-30", 16, 0);
//绘制按钮
DrawButton(90, 195, 60, 20, (u8*)"返回", 1);
}


## 重要屏幕测试相关函数

### 单人对战下棋函数

void One_test(void)//双人对战屏幕扫描
{
u16 x, y;
static int xChess = 0;
static int yChess = 0;
// static int xPre = 0;
// static int yPre = 0;
static uint8_t State = 0;

//判断触摸屏是否被按下
if (tp_dev.sta&TP_PRES_DOWN)
{
while(1)
{
tp_dev.scan(0);
x = tp_dev.x[0];
y = tp_dev.y[0];
if(tp_dev.sta&TP_PRES_DOWN)   //触摸屏被按下
{
if(tp_dev.x[0]<CHESSBOARD_END_X&&tp_dev.y[0]<CHESSBOARD_END_Y)
{
if(tp_dev.x[0]>CHESSBOARD_START_X &&tp_dev.y[0]>CHESSBOARD_START_Y)
{
if(((x - CHESSBOARD_START_X )%CHESSGRID_SIZE)<=7)
xChess = (x - CHESSBOARD_START_X ) / CHESSGRID_SIZE;
else
xChess = ((x - CHESSBOARD_START_X ) / CHESSGRID_SIZE)+1;
if((yChess = (y - CHESSBOARD_START_Y ) % CHESSGRID_SIZE)<7)
yChess = (y - CHESSBOARD_START_Y ) / CHESSGRID_SIZE;
else
yChess = (y - CHESSBOARD_START_Y ) / CHESSGRID_SIZE+1;
//      if (g_ChessNum%2)delay_ms(300);
if((g_ChessNum%2)==0)
DrawChess(xChess, yChess, g_ChessNum, 1);
State = GameOver(xChess, yChess);
if(State==1||State==2)
{
POINT_COLOR = WHITE;
LCD_DrawRectangle(18, 138, 222, 178);
LCD_DrawRectangle(19, 139, 221, 177);
LCD_Fill(20, 140, 220, 176, BLACK);
BACK_COLOR = BLACK;
switch(State)
{
case 1:
Show_Str(20 + (200 - 16*2)/2, 150, 200, 16, (u8*)"和棋", 16, 0);
break;
case 2:
if (g_Mode == 1)
{
if (g_ChessNum % 2)
{
POINT_COLOR=RED;
Show_Str((240 - 16*4)/2, 150, 200, 16, (u8*)"你赢啦！！", 16, 0);
}
else
{
Show_Str((240 - 16*3)/2, 150, 200, 16, (u8*)"很遗憾 你输了", 16, 0);
}
}
delay_ms(1000);//延时提示1秒
Recover();
Over_test();
break;
}
}
}
}
else
{
if (x > 5 && x < 85 && y > 285 && y < 310)//重新开始
ResStart();
if (x > 87 && x < 135 && y > 285 && y < 310)//悔棋
{
if(g_Mode==1)
RetractChess();
}
if(x > 137 && x < 185 && y > 285 && y < 310)
{
//计算AI下子坐标
GetAIPoint(&xChess, &yChess);
delay_ms(10);
}
if (x > 187 && x < 236 && y > 285 && y < 310)//返回
{
ResStart();
GameInit();
}
}
}
else
{
if(!State)
{
if ((g_ChessNum>0)&&(g_ChessNum%2==1))
{
//计算AI下子坐标
GetAIPoint(&xChess, &yChess);
if((g_ChessNum%2==1))
DrawChess(xChess, yChess, g_ChessNum, 1);
State = GameOver(xChess, yChess);
if(State==1||State==2)
{
POINT_COLOR = WHITE;
LCD_DrawRectangle(18, 138, 222, 178);
LCD_DrawRectangle(19, 139, 221, 177);
LCD_Fill(20, 140, 220, 176, BLACK);
BACK_COLOR = BLACK;
switch(State)
{
case 1:
Show_Str(20 + (200 - 16*2)/2, 150, 200, 16, (u8*)"和棋", 16, 0);
break;
case 2:
if (g_Mode == 1)
{
if (g_ChessNum % 2)
{
POINT_COLOR=RED;
Show_Str((240 - 16*4)/2, 150, 200, 16, (u8*)"你赢啦！！", 16, 0);
}
else
{
Show_Str((240 - 16*3)/2, 150, 200, 16, (u8*)"很遗憾 你输了", 16, 0);
}
}
delay_ms(1000);//延时提示1秒
Recover();
Over_test();
break;
}
}
}
}
else
{
t++;
if(t==10)
{
t=0;
}
}
}
}
}else delay_ms(10); //没有按键按下的时候
}


### 有一方胜利后调用函数

void Recover(void)
{
u8 m,n;
DrawChessBoard();//恢复棋盘结束前的模样
for (m= 0; m < 15; m++)
{
for (n = 0; n < 15; n++)
{
if (g_Chess[m][n] > 0)
{
int num = g_Chess[m][n];
DrawChess(m, n, num-1, 0);
}
}
}
}


void Over_test(void)
{
int a,b;
while(1)
{
tp_dev.scan(0);
a = tp_dev.x[0];
b = tp_dev.y[0];
if(tp_dev.sta&TP_PRES_DOWN)   //触摸屏被按下
{
if (a > 5 && a < 85 && b > 285 && b < 310)//重新开始
{
ResStart();
}
if (a > 87 && a < 135 && b > 285 && b < 310)//悔棋
{
RetractChess();
Recover();
Two_test();
}
if (a > 187 && a < 236 && b > 285 && b < 310)//返回
{
ResStart();
GameInit();
}
}
}
}


# 实际效果视频链接

11-09

04-14
03-20
06-14 3561
05-26 4794
05-30
10-31
11-08
02-20 4731
07-05 6352
11-13
©️2020 CSDN 皮肤主题: 撸撸猫 设计师:C马雯娟