Witam Cię ponownie!
Święta za pasem, a wraz z nimi kilka dni wolnego od pracy. To czas, kiedy zastanawiam się, jak ugryźć naukę programowania w środku świątecznego zamieszania. Pytanie brzmi: dać sobie odrobinę spokoju czy kontynuować codzienną rutynę nauki?
Kiedyś wspominałem, że nauka programowania bywa irytująca. Długotrwały brak efektów może działać motywująco lub wręcz przeciwnie, niszczyć zapał. Osobiście, staram się traktować niepowodzenia jako wyzwania. Porażki postrzegać jako wodę na młyn. Gdy napotykam błąd, poświęcam czas na jego rozwiązanie, jednak zdaję sobie sprawę, że nieustępliwość ma swoje ograniczenia. Wielogodzinne ślęczenie przed komputerem wcale nie musi oznaczać, że rozwiążasz dany problem. Jednocześnie przeciążasz układ nerwowy do granic wytrzymałości, a kolejne sesje nauki stają się męczące. Następnego dnia masz serdecznie dość wszystkiego, gdy pomyślisz, że trzeba wracać kodu, przez który wczoraj rwałeś włosy z głowy.
Jak zatem znaleźć złoty środek? Zapraszam do lektury!
Podsumowanie tygodnia
🚀 Programowanie
Rozwój gry Warcaby - 2h dziennie
Serializacja i operacje wejścia/wyjścia (I/O)
🚀 Blog / marka własna
Pierwsza oficjalna publikacja na LinkedIn pod własnym nazwiskiem
Artykuł na Blog - pisać min. 1 akapit dziennie
🚀 Szlifowanie skilli:
Praca głęboka - minimum 2h dziennie
Zasada 30% teorii / 70% pisania kodu
Praca nad KISS
Angielski / Hiszpański (wymiennie, minimum 30 min dziennie)
Postęp
- Rozwój gry Warcaby o inteligentnego przeciwnika -
in progress
- Serializacja i operacje I/O:
- Serializable Interface -
done
- Ogólny schemat przebiegu serializacji -
done
- Schemat deserializacji -
done
- Piątkowa powtórka materiału -
done
Napotkane trudności
- Aktualnie piszę kod konsolowej gry Warcaby
- Rozgrywka przebiega z “inteligentnym” komputerem, którego logika ruchów opiera się na analizie ryzyka utraty pionka przed kolejnym ruchem
- Metoda wyszukuje pionków iterując przez całą planszę w pętli
for
- Gdy program znadzie pionek, uruchamia sekwencję metod, które analizują, czy komputer może zbić mojego pionka, a następnie czy warto taki ruch wykonać, gdyż sam moze przy tym stracić pionka
- Jeśli istnieje takie ryzyko, program sprawdza, czy pionek może wykonać inny ruch. I tutaj taka sama analiza jak dla poprzedniego ruch
- Gdy wszystkie możliwe ruchy wiążą się z utratą pionków przez komputer, wtedy program wybiera losowy pionek przy użyciu metody z klasy
Random
- Temat jest niezwykle skomplikowany, ponieważ w grze pojawiają się różne scenariusze wydarzeń i trzeba to wszystko wziąć pod uwagę
- Wiem, że wiele fragmentów kodu się powtarza, ale izolowanie z tego osobnych metod i upraszanie kodu pozostawiłem sobie na moment, w którym uda mi się stworzyć całą logikę ruchów komputera
Jeśli chcesz zobaczyć kod z klasy Computer, rozwiń pole klikając ptaszka po lewej stronie
import java.util.Random; public class Computer { final static char computerPAWN = 'X'; static int compPawnNumbers = 12; final static char computerQueenPawn = '#'; private boolean movePerformed = false; public void findPawnAndMove() { for (int i = 8; i >= 0; i--) { for (int j = 0; j <= 8; j++) { if (Board.board[i][j] == computerPAWN) { movePerformed = false; System.out.println(i + " / " + j); int compRow = i; int compColumn = j; int rowBelow = compRow + 1; int twoRowsBelow = compRow + 2; int threeRowsBelow = compRow + 3; performBestMove(compRow, compColumn, rowBelow, twoRowsBelow, threeRowsBelow); } } } } private boolean isRiskAfterMove(int compColumn, int twoRowsBelow) { boolean isRisk = false; if (compColumn == 0 || compColumn == 1) { if((Board.board[twoRowsBelow][compColumn] == Player.playerPAWN || Board.board[twoRowsBelow][compColumn + 2] == Player.playerPAWN)) isRisk = true; } else if(compColumn == 6 || compColumn == 7){ if ((Board.board[twoRowsBelow][compColumn] == Player.playerPAWN || Board.board[twoRowsBelow][compColumn - 2] == Player.playerPAWN)) isRisk = true; } else if(compColumn >= 2 || compColumn <=5) { if(Board.board[twoRowsBelow][compColumn] == Player.playerPAWN || Board.board[twoRowsBelow][compColumn - 2] == Player.playerPAWN || Board.board[twoRowsBelow][compColumn + 2] == Player.playerPAWN) isRisk = true; } return isRisk; } private boolean isRiskAfterCapture(int compColumn, int twoRowsBelow, int threeRowsBelow){ boolean isRisk = false; if (compColumn == 0 || compColumn == 1 || compColumn == 2) { if((Board.board[threeRowsBelow][compColumn + 1] == Player.playerPAWN || Board.board[twoRowsBelow][compColumn + 3] == Player.playerPAWN)) { isRisk = true; } } else if(compColumn == 5 || compColumn == 6 || compColumn == 7){ if ((Board.board[threeRowsBelow][compColumn - 1] == Player.playerPAWN || Board.board[twoRowsBelow][compColumn - 3] == Player.playerPAWN)) isRisk = true; } else if(compColumn >= 3 || compColumn <=4) { if((Board.board[threeRowsBelow][compColumn - 1] == Player.playerPAWN || Board.board[twoRowsBelow][compColumn - 3] == Player.playerPAWN) || (Board.board[threeRowsBelow][compColumn + 1] == Player.playerPAWN || Board.board[twoRowsBelow][compColumn + 3] == Player.playerPAWN)) isRisk = true; } return isRisk; } private void performBestMove(int compRow, int compColumn, int rowBelow, int twoRowBelow, int threeRowsBelow) { if (!isRiskAfterCapture(compColumn, threeRowsBelow, threeRowsBelow)){ capturePawn(compRow, compColumn, rowBelow, threeRowsBelow); movePerformed = true; } else if (!isRiskAfterMove(compColumn, threeRowsBelow)) { jumpToField(compRow, compColumn, rowBelow); movePerformed = true } } private boolean isPlayerOnLeft(int compColumn, int rowBelow){ int leftColumn = compColumn - 1; return(Board.board[rowBelow][leftColumn] == Player.playerPAWN); } private boolean isPlayerOnRight(int compColumn, int rowBelow){ int rightColumn = compColumn + 1; return(Board.board[rowBelow][rightColumn] == Player.playerPAWN); } private boolean isPlayerOnBothSides(int compColumn, int rowBelow){ return (isPlayerOnLeft(compColumn, rowBelow) && isPlayerOnRight(compColumn, rowBelow)); } private void capturePawn(int compRow, int compColumn,int rowBelow, int twoRowsBelow) { int columnOnLeft = compColumn - 1; int columnOnRight = compColumn + 1; int leftAfterCapture = compColumn - 2; int rightAfterCapture = compColumn + 2; if (compColumn == 0 || compColumn == 1) { if (isPlayerOnRight(compColumn, rowBelow) && Board.board[twoRowsBelow][rightAfterCapture] == Board.emptyField) { Board.board[compRow][compColumn] = Board.emptyField; Board.board[rowBelow][columnOnRight] = Board.emptyField; Board.board[twoRowsBelow][rightAfterCapture] = Computer.computerPAWN; Player.playerPawnNumbers -= 1; GameLogic.currentPlayer = "Human"; } } else if (compColumn == 6 || compColumn == 7) { if (isPlayerOnLeft(compColumn, rowBelow) && Board.board[twoRowsBelow][leftAfterCapture] == Board.emptyField) { Board.board[compRow][compColumn] = Board.emptyField; Board.board[rowBelow][columnOnLeft] = Board.emptyField; Board.board[twoRowsBelow][leftAfterCapture] = Computer.computerPAWN; Player.playerPawnNumbers -= 1; GameLogic.currentPlayer = "Human"; } } else if(compColumn >= 2 || compColumn <= 5){ if (isPlayerOnBothSides(compColumn, rowBelow)) { if (Board.board[twoRowsBelow][leftAfterCapture] == Board.emptyField && Board.board[twoRowsBelow][rightAfterCapture] == Board.emptyField) { Random random = new Random(); int randomColumn = (random.nextBoolean() ? leftAfterCapture : rightAfterCapture); if (randomColumn == leftAfterCapture) { System.out.println("random left"); Board.board[compRow][compColumn] = Board.emptyField; Board.board[rowBelow][columnOnLeft] = Board.emptyField; Board.board[twoRowsBelow][leftAfterCapture] = computerPAWN; Player.playerPawnNumbers -= 1; GameLogic.currentPlayer = "Human"; } else { Board.board[compRow][compColumn] = Board.emptyField; Board.board[rowBelow][columnOnRight] = Board.emptyField; Board.board[twoRowsBelow][rightAfterCapture] = computerPAWN; Player.playerPawnNumbers -= 1; GameLogic.currentPlayer = "Human"; } } } else if (isPlayerOnLeft(compColumn, rowBelow)) { if (Board.board[twoRowsBelow][leftAfterCapture] == Board.emptyField) { Board.board[compRow][compColumn] = Board.emptyField; System.out.println("Board.board[compRow][compColumn] = Board.emptyField;"); Board.board[rowBelow][columnOnLeft] = Board.emptyField; System.out.println("Board.board[rowBelow][columnOnLeft] = Board.emptyField;"); Board.board[twoRowsBelow][leftAfterCapture] = computerPAWN; System.out.println("Board.board[rowBelow][leftAfterCapture] = computerPAWN;"); Player.playerPawnNumbers -= 1; GameLogic.currentPlayer = "Human"; } } else if (isPlayerOnRight(compColumn, rowBelow)) { if (Board.board[twoRowsBelow][rightAfterCapture] == Board.emptyField) { Board.board[compRow][compColumn] = Board.emptyField; Board.board[rowBelow][columnOnRight] = Board.emptyField; Board.board[twoRowsBelow][rightAfterCapture] = computerPAWN; Player.playerPawnNumbers -= 1; GameLogic.currentPlayer = "Human"; } } } } private void jumpToField(int compRow, int compColumn, int rowBelow) { Random random = new Random(); int leftColumn = compColumn - 1; int rightColumn = compColumn + 1; if (compColumn == 0 || compColumn == 7) { if(compColumn == 0 && Board.board[rowBelow][rightColumn] == Board.emptyField){ Board.board[compRow][compColumn] = Board.emptyField; Board.board[rowBelow][rightColumn] = computerPAWN; } else if(compColumn == 7 && Board.board[rowBelow][leftColumn] == Board.emptyField){ Board.board[compRow][compColumn] = Board.emptyField; Board.board[rowBelow][leftColumn] = computerPAWN; } } else { if (Board.board[rowBelow][leftColumn] == Board.emptyField && Board.board[rowBelow][rightColumn] == Board.emptyField) { int randomColumn = (random.nextBoolean() ? leftColumn : rightColumn); Board.board[compRow][compColumn] = Board.emptyField; Board.board[rowBelow][randomColumn] = computerPAWN; } else { if (Board.board[rowBelow][leftColumn] == Board.emptyField) { Board.board[compRow][compColumn] = Board.emptyField; Board.board[rowBelow][leftColumn] = computerPAWN; } else if (Board.board[rowBelow][rightColumn] == Board.emptyField) { Board.board[compRow][compColumn] = Board.emptyField; Board.board[rowBelow][rightColumn] = computerPAWN;; } } } movePerformed = true; } }
Narzędzia i materiały
- Wspieranie się ChatemGPT
- Head First Java 3rd Edition
Reflekcje i wnioski
- Ostatnie dni toczyłem bój z błędami w kodzie. Długotrwała konfrontacja z klawiaturą sprawiła, że zaczęły pojawiać się chwile zwątpienia i zmęczenia
- Zdaję sobie sprawę, że krótki czas odseparowania od kodu mógłby pomóc spojrzeć niego z nową perspektywą
- Co zatem zrobić? Odpuścić podczas świąt, czy może podjąć kolejną próbę i wytrwać w rutynie mimo wszystko
- Postaram się znaleść balans i podczas nadchodzących dni poświęce jedynie godzinę dziennie na pisanie kodu oraz napiszę 1 akapit do nowego artykułu na blog. Dlaczego? Bo doświadczenie nauczyło mnie, że zbyt długie odseparowanie od kodu sprawia, że powrót do nauki staje się trudniejszy. Często zdarza się, że nie rozumiem połowy napisanego wcześniej kodu, a kilka długich chwil mija, zanim ponownie połapię się, o co w nim właściwie chodziło
ŻYCZĘ CI WESOŁYCH ŚWIĄT!
Cele - kolejny tydzień
🚀 Programowanie
Rozwój gry Warcaby (1h Święta, 2h po Świętach)
🚀 Blog / marka własna
Artykuł na Blog - pisać min. 1 akapit dziennie
🚀 Szlifowanie skilli:
Praca głęboka - minimum 2h dziennie
Zasada 30% teorii / 70% pisania kodu
Praca nad KISS
Śledź mnie na LinkedIn:
Newsletter:
Jeśli masz jakieś sugestie lub pytania, proszę napisz do mnie wiadomość: kuba@javampokaze.pl