30天自制操作系统吧 关注:1,380贴子:4,763
  • 3回复贴,共1

第一个鼠标应用 <井字棋游戏>

只看楼主收藏回复


//zjq.c
#include "apilib.h"
#include <stdio.h>
#include <string.h>
int rand(void);/*产生0~32767的随机数*/
void init_x(int win, unsigned char *buf, int x0, int y0);
void init_o(int win, unsigned char *buf, int x0, int y0);
void init_bc(int win, unsigned char *buf, int x0, int y0);
void init_game(int win, unsigned char *buf);
void game_start(int win, unsigned char *buf);
void win_onclick(int win, unsigned char *buf, int mx, int my);
void init_pre(int win, unsigned char *buf);
void game_click(int win, unsigned char *buf, int x, int y);
void game_end(int win, int now);
int btnw=32, btnh=32, w=220, h=180; //每一格的尺寸
int game_status = 0; //0.未开始 1.开始 2.结束
int bc = 8; //背景色 0xc6c6c6
static char ico_x[32][32] = { //X
"0000........................0000",
".0000......................0000.",
"..0000....................0000..",
"..0000....................0000..",
"...0000..................0000...",
"....0000................0000....",
".....0000..............0000.....",
".....0000..............0000.....",
"......0000............0000......",
"......0000............0000......",
".......0000..........0000.......",
"........0000........0000........",
".........0000......0000.........",
"..........0000....0000..........",
"...........0000..0000...........",
"...........0000000000...........",
"...........0000000000...........",
"...........0000..0000...........",
"..........0000....0000..........",
".........0000......0000.........",
"........0000........0000........",
".......0000..........0000.......",
"......0000............0000......",
"......0000............0000......",
".....0000..............0000.....",
".....0000..............0000.....",
"....0000................0000....",
"...0000..................0000...",
"...0000..................0000...",
"..0000....................0000..",
".0000......................0000.",
"0000........................0000"
};
static char ico_o[32][32] = { //O
"............22222222............",
".........22222222222222.........",
".......222222......222222.......",
"......2222............2222......",
".....222................222.....",
"....222..................222....",
"...222....................222...",
"..222......................222..",
"..22........................22..",
".222........................222.",
".22..........................22.",
".22..........................22.",
"222..........................222",
"22............................22",
"22............................22",
"22............................22",
"22............................22",
"22............................22",
"22............................22",
"222..........................222",
".22..........................22.",
".22..........................22.",
".222........................222.",
"..22........................22..",
"..222......................222..",
"...222....................222...",
"....222..................222....",
".....222................222.....",
"......2222............2222......",
".......222222......222222.......",
".........22222222222222.........",
"............22222222............"
};
//记录游戏点击的落子是x还是o, 1.x, 2.o
//三行三列正斜反斜(8种情况)有相同时结束
int game[3][3] = {
{0,0,0},
{0,0,0},
{0,0,0}
};
int game_now = 0; //当前落子, 0.清除, 1.x, 2.o
void HariMain(void)
{
int win;
int mx=0, my=0, mbtn=0, mx0=0, my0=0, mbtn0=0;
char buf[w * h];
api_initmalloc();
win = api_openwin(buf, w, h, -1, "井字棋");
init_game(win, buf);
for (;;) {
mx = api_getmousex();
my = api_getmousey();
mbtn = api_getmousebtn();
if((mx == mx0) && (my == my0) && (mbtn == mbtn0)) {
sleep(1);
//api_sleep(1); //这个还有bug未解决先弃用
continue;
}
if ((mbtn & 0x01) != 0) { //单击
win_onclick(win, buf, mx, my);
}
mx0 = mx;
my0 = my;
mbtn0 = mbtn;
}
api_end();
}
void win_onclick(int win, unsigned char *buf, int mx, int my) {
int x, y, bs=40, b=2; //九格x,y坐标, [0,0]代表第一格即左上角的格
if (mx < 0 || my < 0) { //不在窗体内的点击 不操作
return;
}
if ((game_status == 0) && (10 <= mx) && (mx <= 52) && (130 <= my) && (my <= 158)) { //点击了开始按钮
game_start(win, buf);
}
if ((game_status == 1) && (74 <= mx) && (mx <= 200) && (38 <= my) && (my <= 164)) { //点击了九格之内
//找出具体点在哪格
x = (int)((my - 38) / (bs + b));
y = (int)((mx - 72) / (bs + b));
game_click(win, buf, x, y);
}
if ((game_status == 2) && (10 <= mx) && (mx <= 52) && (130 <= my) && (my <= 158)) { //点击任意地方重新开始
init_game(win, buf);
}
}
void game_click(int win, unsigned char *buf, int x, int y) {
int x0, y0; //实际坐标值
if (game[x][y] > 0) { return; } //已经有子的不可以再下
x0 = 74 + 42 * y + 4; //格子是40*40, 边是2, 图标是32*32, 所以要从格子的 4*4开始画图
y0 = 38 + 42 * x + 4;
if (game_now == 1) {
init_x(win, buf, x0, y0);
} else if (game_now == 2) {
init_o(win, buf, x0, y0);
}
game[x][y] = game_now;
game_now = game_now == 1 ? 2 : 1; //换另一个下
init_pre(win, buf);
chk_end(win, buf);
}
void chk_end(int win, unsigned char *buf) {
int x,y,i;
for (x = 0; x < 3; x++){ //行
if (game[x][0] > 0 && game[x][0] == game[x][1] && game[x][1] == game[x][2]) {
game_end(win, game[x][0]);
}
}
for (y = 0; y < 3; y++){ //列
if (game[0][y] > 0 && game[0][y] == game[1][y] && game[1][y] == game[2][y]) {
game_end(win, game[0][y]);
}
}
if (game[0][0] > 0 && game[0][0] == game[1][1] && game[1][1] == game[2][2]) { //反斜
game_end(win, game[0][0]);
}
if (game[0][2] > 0 && game[0][2] == game[1][1] && game[1][1] == game[2][0]) { //正斜
game_end(win, game[0][2]);
}
i = 1;
for (x = 0; x < 3; x++) {
for (y = 0; y < 3; y++) {
if (game[x][y] == 0) {
i = 0;
break;
}
}
}
if (i == 1) {
game_end(win, 0); //平局
}
}
void game_end(int win, int now) {
game_status = 2; //游戏结束
char *s;
if (now == 0) {
s = "平局了!";
} else {
sprintf(s, "%s 羸了~", now == 1 ? "X" : "O");
}
api_boxfilwin(win, 60, 50, 158, 88, 6);
api_putstrwin(win, 84, 60, 0 /*黑色*/, strlen(s), s); //COL8_000000
api_refreshwin(win, 60, 50, 158, 88);
api_boxfilwin(win, 10, 130, 52, 158, 6 /*浅蓝色*/); //开始按钮
api_putstrwin(win, 15, 136, 0 /*黑色*/, 4, "重来"); //COL8_000000
api_refreshwin(win, 10, 130, 52, 158);
}
void init_pre(int win, unsigned char *buf) {
if (game_now == 1) {
init_x(win, buf, 15, 35);
init_bc(win, buf, 15, 77);
} else if (game_now == 2) {
init_bc(win, buf, 15, 35);
init_o(win, buf, 15, 77);
}
}
void game_start(int win, unsigned char *buf) {
int begin=0,i;
if(game_status == 1) { return;} //已经点过开始了
game_status = 1;
i = api_getsecond(); //时间因子(秒数^_^)
for(; i >= 0; i--) { begin = rand();} //加入了时间因子更随机
if(begin % 2 == 0){ //第一个是X, 把O干掉
game_now = 1;
} else { //第一个是O, 把X干掉
game_now = 2;
}
init_pre(win, buf);
api_boxfilwin(win, 10, 130, 52, 158, 6 /*浅蓝色*/); //开始按钮
api_putstrwin(win, 15, 136, 15, 4, "开始"); //COL8_000000
api_refreshwin(win, 10, 130, 52, 158);
}
void init_game(int win, unsigned char *buf) {
int i, bx=72, by=36, bs=40, b=2, x, y;
game_status = 0;
for(x = 0; x < 3; x++){
for(y = 0; y < 3; y++){
game[x][y] = 0;
}
}
for (y = 21; y < h - 5; y++) {//整个界面重画,除标题
for (x = 5; x < w - 5; x++) {
buf[y * w + x] = bc;
}
}
api_refreshwin(win, 5, 21, w - 5, h - 5); //刷新界面
init_x(win, buf, 15, 35);
init_o(win, buf, 15, 77);
api_boxfilwin(win, 10, 130, 52, 158, 6 /*浅蓝色*/); //开始按钮
api_putstrwin(win, 15, 136, 0 /*黑色*/, 4, "开始"); //COL8_000000
/*开始画格子*/
for(i = 0; i < 4; i++) { //每格式大小为 40 * 40, 图大小为 32 * 32
api_boxfilwin(win, bx, by + i * (bs+b), bx + 2 + (bs+b)*3, by + 2 + i * (bs+b), 15 /*暗灰色*/); //横
api_boxfilwin(win, bx + i * (bs+b), by, bx + 2 + i * (bs+b), by + 2 + (bs+b)*3, 15 /*暗灰色*/); //竖
}
api_refreshwin(win, 0, 0, w, h);
/*可点击位置*/
/*
1. 开始按钮: ([10,130][52,158])
2. 井字格
([74, 38][114, 78]), ([116, 38][156, 78]), ([158, 38][198, 78])
([74, 80][114,120]), ([116, 80][156,120]), ([158, 80][198, 80])
([74,122][114,162]), ([116,122][156,162]), ([158,162][198,162])
*/
}
void init_x(int win, unsigned char *buf, int x0, int y0){ //刷新范围是x0,y0=>x0+32,y0+32
int x, y, xs, ys;
if(btnh + y0 > h) {
ys = h;
} else {
ys = btnh + y0;
}
if(btnw + x0 > w) {
xs = w;
} else {
xs = btnw + x0;
}
for (y = y0; y < ys; y++) {
for (x = x0; x < xs; x++) {
if (ico_x[y-y0][x-x0] == '.') {
buf[y * w + x] = bc;
} else {
buf[y * w + x] = ico_x[y-y0][x-x0] - 48; //字符数字转数字
}
}
}
api_refreshwin(win, x0, y0, xs, ys);
return;
}
void init_o(int win, unsigned char *buf, int x0, int y0){ //刷新范围是x0,y0=>x0+32,y0+32
int x, y, xs, ys;
if(btnh + y0 > h) {
ys = h;
} else {
ys = btnh + y0;
}
if(btnw + x0 > w) {
xs = w;
} else {
xs = btnw + x0;
}
for (y = y0; y < ys; y++) {
for (x = x0; x < xs; x++) {
if (ico_o[y-y0][x-x0] == '.') {
buf[y * w + x] = bc;
} else {
buf[y * w + x] = ico_o[y-y0][x-x0] - 48; //字符数字转数字
}
}
}
api_refreshwin(win, x0, y0, xs, ys);
return;
}
void init_bc(int win, unsigned char *buf, int x0, int y0){ //刷新范围是x0,y0=>x0+32,y0+32
int x, y, xs, ys;
if(btnh + y0 > h) {
ys = h;
} else {
ys = btnh + y0;
}
if(btnw + x0 > w) {
xs = w;
} else {
xs = btnw + x0;
}
for (y = y0; y < ys; y++) {
for (x = x0; x < xs; x++) {
buf[y * w + x] = bc;
}
}
api_refreshwin(win, x0, y0, xs, ys);
return;
}
鼠标api相关
//console.c
} else if (edx == 30) { /* 鼠标X坐标 */
reg[7] = sht->height == shtctl->top -1 ? (MOUSEX - sht->vx0) : -1; //当前窗体在最前面时才返回值
} else if (edx == 31) { /* 鼠标Y坐标 */
reg[7] = sht->height == shtctl->top -1 ? (MOUSEY - sht->vy0) : -1;
} else if (edx == 32) { /* 鼠标按键值 */
reg[7] = MOUSEBTN;
} else if (edx == 33) { /* 休眠 */
api33_sleep(cons->timer, task, ecx);
} else if (edx == 34) { /* 获取秒数(应用中随机数时会用到) */
reg[7] = get_sec_hex();
}


IP属地:福建1楼2022-09-28 14:06回复
    鼠标api相关
    你用了5个Api,可以简化为一个。33,34设法革除不要。


    IP属地:上海2楼2022-10-03 10:58
    收起回复
      谢谢大佬提醒, 已改成一个接口
      } else if (edx == 36) { /* 鼠标API */
      int x, y, b, z;
      unsigned long int mdec = 0; /* yyyyxxxxbb 无符号int最大值4294967295, 正常是宽屏, x,y倒过来存, 所以最大鼠标坐标[9672,4294] */
      sht = (struct SHEET *) ebx;
      /* 不在当前窗体或鼠标不在窗体内的返回-1 */
      x = ((sht->height != shtctl->top -1) || (MOUSEX - sht->vx0 < 0) || (MOUSEX - sht->vx0 - sht->bxsize > 0)) ? -1 : (MOUSEX - sht->vx0);
      y = ((sht->height != shtctl->top -1) || (MOUSEY - sht->vy0 < 0) || (MOUSEY - sht->vy0 - sht->bysize > 0)) ? -1 : (MOUSEY - sht->vy0);
      b = sht->height == shtctl->top -1 ? MOUSEBTN : 0;
      z = 1; /* x,y是否存在负数,1.正数,-1.负数 */
      if (x < 0) { z = -1; x *= -1; /* 转为正数 */ }
      if (y < 0) { z = -1; y *= -1; /* 转为正数 */ }
      mdec += y * 1000000; //Y
      mdec += x * 100; //X
      mdec += b; //Btn
      mdec *= z;
      reg[7] = mdec;
      }
      APP中使用
      for (;;) {
      api_sleep(10);
      mdec = api_getmouse(win);
      if (mdec < 0) { continue; }
      my = (int) (mdec / 1000000);
      mdec %= 1000000;
      mx = (int) (mdec / 100);
      mdec %= 100;
      mbtn = (int) mdec;
      if((mx == mx0) && (my == my0) && (mbtn == mbtn0)) { continue; }
      mx0 = mx; my0 = my; mbtn0 = mbtn;
      if ((mbtn & 0x01) != 0) { //单击
      win_onleftclick(mx, my);
      } else if((mbtn & 0x02) != 0) { //右键单击
      win_onrightclick(mx, my);
      } else if((mbtn & 0x03) != 0) { //中键单击
      win_onmiddleclick(mx, my);
      } else if((mbtn & 0x04) != 0) { //左右键同击
      win_onleftrightclick(mx, my);
      } else { //鼠标经过事件
      win_onmouseover(mx, my);
      }
      }


      IP属地:福建3楼2022-10-08 11:27
      回复