Prolific
Специалист
Опять же делал для конкурса.
Предисловие. Просмотрев пару работ, по крайней мере те, кто выложил, пришел к выводу, что я сильно ленивый, чтобы писать кучу комбинаций в массив, я не лентяй, чтобы делать проверку для 9 клеток и я не гонюсь за сверх оптимизацией. Согласен, проверка массивом будет работать гораздо быстрее, но для переписывания всех комбинаций в массив затрат умственных сил нужно меньше и, что самое главное скрипт не является универсальным. Если порядок матрицы увеличит на один, уже нужно будет думать, тогда как мои алгоритмы нуждаются только в ограничениях и мелких изменениях. Я не оправдываюсь, а лишь описываю свой подход к решению проблем. Есть несколько лишних переменных, но делал я их для читабельности и чтобы не запутаться. Насчет дизайна я и не буду даже говорить, менять правила в середине конкурса нечестно (оказывается не только в середине), но это уже совсем другая история. Ну и собственно оценивайте:
Предисловие. Просмотрев пару работ, по крайней мере те, кто выложил, пришел к выводу, что я сильно ленивый, чтобы писать кучу комбинаций в массив, я не лентяй, чтобы делать проверку для 9 клеток и я не гонюсь за сверх оптимизацией. Согласен, проверка массивом будет работать гораздо быстрее, но для переписывания всех комбинаций в массив затрат умственных сил нужно меньше и, что самое главное скрипт не является универсальным. Если порядок матрицы увеличит на один, уже нужно будет думать, тогда как мои алгоритмы нуждаются только в ограничениях и мелких изменениях. Я не оправдываюсь, а лишь описываю свой подход к решению проблем. Есть несколько лишних переменных, но делал я их для читабельности и чтобы не запутаться. Насчет дизайна я и не буду даже говорить, менять правила в середине конкурса нечестно (оказывается не только в середине), но это уже совсем другая история. Ну и собственно оценивайте:
PHP:
//Крестики VS нолики By Prolific
#include <a_samp>
#include <dc_cmd>
#include <sscanf2>
new PlayerText: kvadrat[MAX_PLAYERS][81];
new PlayerText: text[MAX_PLAYERS][81];
new PlayerText: Exit[MAX_PLAYERS];
new Text: karkas[2];// в конкурсе размерность была 6, забыл исправить
new score[MAX_PLAYERS];//Счет игрока.
new kletka[MAX_PLAYERS][81];//Значение в клетке.
new type[MAX_PLAYERS char];//Крестик или нолик у игрока.
new PlayerText: names[MAX_PLAYERS][2];//Имена игроков в заголовке.
new PlayerText: scores[MAX_PLAYERS][2];//Счеты игроков в заголовке.
new bool:hod[MAX_PLAYERS];
public OnFilterScriptInit()
{
print("\n--------------------------------------");
print(" Krest and null By Prolific ");
print("--------------------------------------\n");
karkas[0] = TextDrawCreate(602.644226, 166.000000, "usebox");
TextDrawLetterSize(karkas[0], 0.000000, 24.312965);
TextDrawTextSize(karkas[0], 381.250366, 255.500000);
TextDrawAlignment(karkas[0], 1);
TextDrawColor(karkas[0], 0);
TextDrawUseBox(karkas[0], true);
TextDrawBoxColor(karkas[0], 102);
TextDrawSetShadow(karkas[0], 0);
TextDrawSetOutline(karkas[0], 0);
TextDrawFont(karkas[0], 0);
karkas[1] = TextDrawCreate(604.049804, 132.166656, "usebox");
TextDrawLetterSize(karkas[1], 0.000000, 28.266670);
TextDrawTextSize(karkas[1], 379.844787, 0.000000);
TextDrawAlignment(karkas[1], 1);
TextDrawUseBox(karkas[1], true);
TextDrawBoxColor(karkas[1], -5963521);
TextDrawFont(karkas[1], 0);
return 1;
}
public OnPlayerClickTextDraw(playerid, Text:clickedid)
{
if(clickedid == Text: INVALID_TEXT_DRAW && type{playerid})
{
ShowPlayerDialog(playerid, 0, 0, "{ffffff}Выход", "{ffffff}Вы действительно хотите закончить игру?", "Да", "Нет");
SelectTextDraw(playerid, 102);
}
return 1;
}
public OnPlayerClickPlayerTextDraw(playerid, PlayerText:playertextid)
{
if(playertextid == Exit[playerid]) return ShowPlayerDialog(playerid, 0, 0, "{ffffff}Выход", "{ffffff}Вы действительно хотите закончить игру?", "Да", "Нет");
for(new i; i < 81; i++)
{
if(playertextid == kvadrat[playerid][i])
{
if(!hod[playerid]) return SendClientMessage(playerid, -1, "Сейчас не ваш ход!");
if(kletka[playerid][i]) return SendClientMessage(playerid, -1, "Эта клетка занята!");
hod[playerid] = false;
hod[GetPVarInt(playerid,"SOPERNIK")] = true;
UpdateKletka(playerid, i);
}
}
return 1;
}
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
switch(dialogid)
{
case 0:
{
if(response)
{
new playerid2 = GetPVarInt(playerid, "SOPERNIK");
HidePanel(playerid);
HidePanel(playerid2);
}
}
case 1:
{
if(response)
{
new playerid2 = GetPVarInt(playerid,"SOPERNIK");
ShowPanel(playerid);
ShowPanel(playerid2);
SetPVarInt(playerid2, "SOPERNIK", playerid);
type{playerid} = 2;
type{playerid2} = 1;
score[playerid] = 0;
score[playerid2] = 0;
UpdateNames(playerid);
UpdateScores(playerid);
if(random(2)) hod[playerid] = true;
else hod[playerid2] = true;
return 1;
}
else
{
SendClientMessage(GetPVarInt(playerid,"SOPERNIK"), -1, "Игрок отказался играть.");
DeletePVar(playerid, "SOPERNIK");
}
}
}
return 1;
}
public OnPlayerConnect(playerid)
{
new Float:x = 389.0, Float:y = 173.0;
for(new i, k; i < 9; i++)
{
for(new j; j < 9; j++)
{
kvadrat[playerid][k] = CreatePlayerTextDraw(playerid, x, y, "LD_SPAC:white");
PlayerTextDrawTextSize(playerid, kvadrat[playerid][k], 22.0, 22.0);
PlayerTextDrawColor(playerid, kvadrat[playerid][k], -1);
PlayerTextDrawFont(playerid, kvadrat[playerid][k], 4);
PlayerTextDrawSetSelectable(playerid, kvadrat[playerid][k], 1);
text[playerid][k] = CreatePlayerTextDraw(playerid, x + 12.0, y, "_");
PlayerTextDrawLetterSize(playerid, text[playerid][k], 0.609297, 2.317500);
PlayerTextDrawAlignment(playerid, text[playerid][k], 2);
PlayerTextDrawColor(playerid, text[playerid][k], 255);
PlayerTextDrawSetShadow(playerid, text[playerid][k], 0);
PlayerTextDrawSetOutline(playerid, text[playerid][k], 0);
PlayerTextDrawBackgroundColor(playerid, text[playerid][k], 51);
PlayerTextDrawFont(playerid, text[playerid][k], 2);
PlayerTextDrawSetProportional(playerid, text[playerid][k], 1);
x += 23.0;
k++;
}
x = 389.0;
y += 23.0;
}
Exit[playerid] = CreatePlayerTextDraw(playerid, 581.903198, 133.000000, "LD_BEAT:cross");
PlayerTextDrawTextSize(playerid, Exit[playerid], 17.335327, 17.500000);
PlayerTextDrawAlignment(playerid, Exit[playerid], 1);
PlayerTextDrawColor(playerid, Exit[playerid], -2640156);
PlayerTextDrawFont(playerid, Exit[playerid], 4);
PlayerTextDrawSetSelectable(playerid, Exit[playerid], 1);
names[playerid][0] = CreatePlayerTextDraw(playerid, 383.250701, 127.166717, "_");
PlayerTextDrawLetterSize(playerid, names[playerid][0], 0.251815, 1.850833);
PlayerTextDrawAlignment(playerid, names[playerid][0], 1);
PlayerTextDrawColor(playerid, names[playerid][0], -1);
PlayerTextDrawSetShadow(playerid, names[playerid][0], 0);
PlayerTextDrawSetOutline(playerid, names[playerid][0], 0);
PlayerTextDrawBackgroundColor(playerid, names[playerid][0], 51);
PlayerTextDrawFont(playerid, names[playerid][0], 2);
PlayerTextDrawSetProportional(playerid, names[playerid][0], 1);
names[playerid][1] = CreatePlayerTextDraw(playerid, 383.313720, 142.750030, "_");
PlayerTextDrawLetterSize(playerid, names[playerid][1], 0.251814, 1.850833);
PlayerTextDrawAlignment(playerid, names[playerid][1], 1);
PlayerTextDrawColor(playerid, names[playerid][1], -1);
PlayerTextDrawSetShadow(playerid, names[playerid][1], 0);
PlayerTextDrawSetOutline(playerid, names[playerid][1], 0);
PlayerTextDrawBackgroundColor(playerid, names[playerid][1], 51);
PlayerTextDrawFont(playerid, names[playerid][1], 2);
PlayerTextDrawSetProportional(playerid, names[playerid][1], 1);
scores[playerid][0] = CreatePlayerTextDraw(playerid, 514.563354, 127.166717, ": 01");
PlayerTextDrawLetterSize(playerid, scores[playerid][0], 0.251814, 1.850833);
PlayerTextDrawAlignment(playerid, scores[playerid][0], 1);
PlayerTextDrawColor(playerid, scores[playerid][0], -1);
PlayerTextDrawSetShadow(playerid, scores[playerid][0], 0);
PlayerTextDrawSetOutline(playerid, scores[playerid][0], 0);
PlayerTextDrawBackgroundColor(playerid, scores[playerid][0], 51);
PlayerTextDrawFont(playerid, scores[playerid][0], 2);
PlayerTextDrawSetProportional(playerid, scores[playerid][0], 1);
scores[playerid][1] = CreatePlayerTextDraw(playerid, 514.563354, 142.750030, ": 02");
PlayerTextDrawLetterSize(playerid, scores[playerid][1], 0.251814, 1.850833);
PlayerTextDrawAlignment(playerid, scores[playerid][1], 1);
PlayerTextDrawColor(playerid, scores[playerid][1], -1);
PlayerTextDrawSetShadow(playerid, scores[playerid][1], 0);
PlayerTextDrawSetOutline(playerid, scores[playerid][1], 0);
PlayerTextDrawBackgroundColor(playerid, scores[playerid][1], 51);
PlayerTextDrawFont(playerid, scores[playerid][1], 2);
PlayerTextDrawSetProportional(playerid, scores[playerid][1], 1);
return 1;
}
public OnPlayerDisconnect(playerid, reason)
{
if(type{playerid})
{
score[playerid] = 0;
for(new i; i < 81; i++) kletka[playerid][i] = 0;
type{playerid} = 0;
hod[playerid] = false;
HidePanel(GetPVarInt(playerid, "SOPERNIK"));
SendClientMessage(GetPVarInt(playerid, "SOPERNIK"), -1, "Ваш соперник завершил игру.");
}
return 1;
}
public OnPlayerDeath(playerid, killerid, reason)
{
if(type{playerid})
{
score[playerid] = 0;
for(new i; i < 81; i++) kletka[playerid][i] = 0;
type{playerid} = 0;
hod[playerid] = false;
HidePanel(GetPVarInt(playerid, "SOPERNIK"));
SendClientMessage(GetPVarInt(playerid, "SOPERNIK"), -1, "Ваш соперник завершил игру.");
}
return 1;
}
stock ShowPanel(playerid)
{
for(new i; i < 81; i++)
{
PlayerTextDrawShow(playerid, kvadrat[playerid][i]);
PlayerTextDrawShow(playerid, text[playerid][i]);
}
for(new i; i < 2; i++) TextDrawShowForPlayer(playerid, karkas[i]);
PlayerTextDrawShow(playerid, Exit[playerid]);
SelectTextDraw(playerid, 102);
}
stock HidePanel(playerid)
{
type{playerid} = 0;
hod[playerid] = false;
DeletePVar(playerid, "SOPERNIK");
for(new i; i < 81; i++)
{
PlayerTextDrawHide(playerid, kvadrat[playerid][i]);
PlayerTextDrawHide(playerid, text[playerid][i]);
}
for(new i; i < 2; i++) TextDrawHideForPlayer(playerid, karkas[i]);
PlayerTextDrawHide(playerid, Exit[playerid]);
CancelSelectTextDraw(playerid);
PlayerTextDrawHide(playerid, names[playerid][0]);
PlayerTextDrawHide(playerid, names[playerid][1]);
PlayerTextDrawHide(playerid, scores[playerid][0]);
PlayerTextDrawHide(playerid, scores[playerid][1]);
}
stock CheckWin(playerid)
{
new pusto;//проверка на ничью
new chet[2];//0 - крестики, 1 - нолики
//пробег по строкам
for(new i, k; i < 9; i++)
{
for(new j; j < 9; j++, k++)
{
if(!kletka[playerid][k])
{
if(chet[0]) chet[0] = 0;//обнуляем если линия не однородна
if(chet[1]) chet[1] = 0;
pusto++;//считаем пустые клетки, если их нет и никто не выйграл, то ничья
continue;
}
if(kletka[playerid][k] == 1)
{
chet[0]++;
if(chet[1]) chet[1] = 0;//лучше проверим, чтобы лишний раз не выполнять 3 действия
}
else if(kletka[playerid][k] == 2)
{
chet[1]++;
if(chet[0]) chet[0] = 0;
}
if(chet[0] == 5) return PlayerWin(playerid, 1);//победа крестиков
else if(chet[1] == 5) return PlayerWin(playerid, 2);//победа ноликов
}
chet[0] = 0;//обнуляем, т.к. делаем новую итерацию
chet[1] = 0;//-||-
}
//по столбцам
for(new i, m; i < 9; i++)
{
for(new j; j < 9; j++)
{
m = j*9+i;
if(!kletka[playerid][m])
{
if(chet[0]) chet[0] = 0;
if(chet[1]) chet[1] = 0;
continue;
}
if(kletka[playerid][m] == 1)
{
chet[0]++;
if(chet[1]) chet[1] = 0;
}
else if(kletka[playerid][m] == 2)
{
chet[1]++;
if(chet[0]) chet[0] = 0;
}
if(chet[0] == 5) return PlayerWin(playerid, 1);
else if(chet[1] == 5) return PlayerWin(playerid, 2);
}
chet[0] = 0;
chet[1] = 0;
}
// проверка вдоль гл. диаг.
for(new i, m; i < 5; i++)
{
for(new j = i; j <= 8; j++)// первая часть + главная диагональ
{
m = 9*j+j-i;
if(!kletka[playerid][m])
{
if(chet[0]) chet[0] = 0;
if(chet[1]) chet[1] = 0;
continue;
}
if(kletka[playerid][m] == 1)
{
chet[0]++;
if(chet[1]) chet[1] = 0;
}
else if(kletka[playerid][m] == 2)
{
chet[1]++;
if(chet[0]) chet[0] = 0;
}
if(chet[0] == 5) return PlayerWin(playerid, 1);
else if(chet[1] == 5) return PlayerWin(playerid, 2);
}
chet[0] = 0;
chet[1] = 0;
if(!i) continue;// обход лишней итерации
for(new j = 9-i-1; j >= 0; j--)// вторая часть
{
m = 9*j+j+i;
if(!kletka[playerid][m])
{
if(chet[0]) chet[0] = 0;
if(chet[1]) chet[1] = 0;
continue;
}
if(kletka[playerid][m] == 1)
{
chet[0]++;
if(chet[1]) chet[1] = 0;
}
else if(kletka[playerid][m] == 2)
{
chet[1]++;
if(chet[0]) chet[0] = 0;
}
if(chet[0] == 5) return PlayerWin(playerid, 1);
else if(chet[1] == 5) return PlayerWin(playerid, 2);
}
chet[0] = 0;
chet[1] = 0;
}
// проверка вдоль побочной диагонали
for(new i = 8, m; i >= 4; i--)
{
for(new j = i; j >= 0; j--)
{
m = 9*j+i-j;
if(!kletka[playerid][m])
{
if(chet[0]) chet[0] = 0;
if(chet[1]) chet[1] = 0;
continue;
}
if(kletka[playerid][m] == 1)
{
chet[0]++;
if(chet[1]) chet[1] = 0;
}
else if(kletka[playerid][m] == 2)
{
chet[1]++;
if(chet[0]) chet[0] = 0;
}
if(chet[0] == 5) return PlayerWin(playerid, 1);
else if(chet[1] == 5) return PlayerWin(playerid, 2);
}
chet[0] = 0;
chet[1] = 0;
for(new j = 9-i, k; j <= 8; j++, k++)// побочная диагональ учтена выше, тут не проверяется
{
m = 9*j+8-k;
if(!kletka[playerid][m])
{
if(chet[0]) chet[0] = 0;
if(chet[1]) chet[1] = 0;
continue;
}
if(kletka[playerid][m] == 1)
{
chet[0]++;
if(chet[1]) chet[1] = 0;
}
else if(kletka[playerid][m] == 2)
{
chet[1]++;
if(chet[0]) chet[0] = 0;
}
if(chet[0] == 5) return PlayerWin(playerid, 1);
else if(chet[1] == 5) return PlayerWin(playerid, 2);
}
chet[0] = 0;
chet[1] = 0;
}
if(!pusto) return PlayerWin(playerid, 3);
return 1;
}
stock PlayerWin(playerid, idx)
{
new playerid2 = GetPVarInt(playerid,"SOPERNIK");
if(type{playerid} == idx)
{
SendClientMessage(playerid, -1, "Вы выйграли");
SendClientMessage(playerid2, -1, "Вы проиграли");
score[playerid]++;
}
else if(type{playerid2} == idx)
{
SendClientMessage(playerid2, -1, "Вы выйграли");
SendClientMessage(playerid, -1, "Вы проиграли");
score[playerid2]++;
}
if(idx == 3)
{
SendClientMessage(playerid2, -1, "Ничья");
SendClientMessage(playerid, -1, "Ничья");
}
for(new i; i < 81; i++)
{
if(kletka[playerid][i])
{
kletka[playerid][i] = 0;
PlayerTextDrawSetString(playerid, text[playerid][i], "_");
PlayerTextDrawSetString(playerid2, text[playerid2][i], "_");
PlayerTextDrawShow(playerid, text[playerid][i]);
PlayerTextDrawShow(playerid2, text[playerid2][i]);
}
}
UpdateScores(playerid);
return 1;
}
stock UpdateKletka(playerid, idx)
{
new playerid2 = GetPVarInt(playerid,"SOPERNIK");
new string[2];
string = type{playerid} == 1 ? ("X") : ("O");
PlayerTextDrawSetString(playerid, text[playerid][idx], string);
PlayerTextDrawSetString(playerid2, text[playerid2][idx], string);
PlayerTextDrawShow(playerid, text[playerid][idx]);
PlayerTextDrawShow(playerid2, text[playerid2][idx]);
kletka[playerid][idx] = type{playerid};
kletka[playerid2][idx] = type{playerid};
CheckWin(playerid);
}
stock UpdateScores(playerid1)
{
new playerid2 = GetPVarInt(playerid1,"SOPERNIK");
new string[10];
format(string, sizeof(string), ": %02d", score[playerid1]);
PlayerTextDrawSetString(playerid1, scores[playerid1][0], string);
PlayerTextDrawSetString(playerid2, scores[playerid1][0], string);
format(string, sizeof(string), ": %02d", score[playerid2]);
PlayerTextDrawSetString(playerid1, scores[playerid1][1], string);
PlayerTextDrawSetString(playerid2, scores[playerid1][1], string);
PlayerTextDrawShow(playerid1, scores[playerid1][0]);
PlayerTextDrawShow(playerid1, scores[playerid1][1]);
PlayerTextDrawShow(playerid2, scores[playerid1][0]);
PlayerTextDrawShow(playerid2, scores[playerid1][1]);
}
stock UpdateNames(playerid1)
{
new playerid2 = GetPVarInt(playerid1,"SOPERNIK");
new string[MAX_PLAYER_NAME];
GetPlayerName(playerid1, string, MAX_PLAYER_NAME);
format(string, sizeof(string), "%s", string);
PlayerTextDrawSetString(playerid1, names[playerid1][0], string);
PlayerTextDrawSetString(playerid2, names[playerid1][0], string);
GetPlayerName(playerid2, string, MAX_PLAYER_NAME);
format(string, sizeof(string), "%s", string);
PlayerTextDrawSetString(playerid1, names[playerid1][1], string);
PlayerTextDrawSetString(playerid2, names[playerid1][1], string);
PlayerTextDrawShow(playerid1, names[playerid1][0]);
PlayerTextDrawShow(playerid1, names[playerid1][1]);
PlayerTextDrawShow(playerid2, names[playerid1][0]);
PlayerTextDrawShow(playerid2, names[playerid1][1]);
}
CMD:krest(playerid, params[])
{
if(sscanf(params, "u", params[0])) return SendClientMessage(playerid, -1, ">> /krest [id]");
if(type{playerid}) return SendClientMessage(playerid, -1, "Вы уже играете!");
if(!IsPlayerConnected(params[0])) return SendClientMessage(playerid, -1, "Игрока нет в сети!");
if(playerid == params[0]) return SendClientMessage(playerid, -1, "Нельзя играть с самим собой!");
SetPVarInt(params[0], "SOPERNIK", playerid);
new name[MAX_PLAYER_NAME];
new string[89];
GetPlayerName(params[0], name, MAX_PLAYER_NAME);
format(string, 72, "Вы предложили сыграть в крестики-нолики игроку %s", name);
SendClientMessage(playerid, -1, string);
GetPlayerName(playerid, name, MAX_PLAYER_NAME);
format(string, sizeof(string), "%s предлагает вам сыграть в крестики-нолики\nНажмите \"Да\" для продолжения.", name);
ShowPlayerDialog(params[0], 1, 0, "Крестики-нолики", string, "Да", "Нет");
return 1;
}
