package game;
import player.AbstractPlayer;
import player.SwingPlayer;
import static game.Card.intColorToText;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Game {
/*
* COLORS:
* GREEN
* RED
* YELLOW
* WHITE
* BLUE
* (COLORED)
*/
final static int GREEN = 0;
final static int RED = 1;
final static int YELLOW = 2;
final static int WHITE = 3;
final static int BLUE = 4;
final static int COLORS = 5;
int NR_PLAYERS = 3;
static int CARDS_PER_PLAYER;
final static int NR_OF_CARDS = 50;
static int CARDS_IN_DECK;
final static int MAX_HINTS = 8;
final static int MAX_THUNDERS = 3;
int hints;
int thunders;
ArrayList<Card> cards;
Card[][] deck;
int[] deckCounter;
ArrayList<Card> trash;
AbstractPlayer[] players;
int currentPlayer;
int selectedPlayer;
int selectedCards;
int chosenColor;
int chosenValue;
boolean useColor;
boolean useValue;
boolean placeCard;
boolean trashCard;
boolean won;
boolean lost;
//UI STUFF
JFrame mainFrame;
JPanel gamePanel;
JPanel hintPanel;
JPanel thunderPanel;
JPanel buttonPanel;
JPanel deckPanel;
JLabel[][] deckUI;
JButton colorButton;
JButton valueButton;
JButton nextMove;
JButton placeCardButton;
JButton trashCardButton;
JLabel[] hintUI;
JLabel[] thunderUI;
JPanel[] playersUI;
public static void main(String[] args) {
Game game = new Game();
game.getPlayer(game.currentPlayer).deactiveCards();
System.out.println("Player " + game.currentPlayer + "'s turn");
}
public Game(){
init();
}
private void init(){
CARDS_PER_PLAYER = (NR_PLAYERS < 3) ? 5 : 4;
hints = MAX_HINTS;
thunders = 0;
createPlayers();
currentPlayer = 0;
resetMoveValues();
addCards();
CARDS_IN_DECK = cards.size();
createUI();
dealCards();
}
public void resetMoveValues(){
selectedPlayer = -1;
chosenColor = -1;
chosenValue = -1;
selectedCards = 0;
useColor = useValue = trashCard = placeCard = false;
}
private void createPlayers(){
players = new AbstractPlayer[NR_PLAYERS];
//playersUI = new JPanel[NR_PLAYERS];
for(int i=0; i<NR_PLAYERS; ++i){
players[i] = new SwingPlayer(CARDS_PER_PLAYER, this);
//playersUI[i] = new JPanel();
}
//players[0].print();
}
private void addCards(){
cards = new ArrayList<>();
deck = new Card[COLORS][5];
deckCounter = new int[5];
trash = new ArrayList<>();
int[] dist = new int[]{3, 2, 2, 2, 1};
int[][] tmp_cards = new int[][]{
dist.clone(),
dist.clone(),
dist.clone(),
dist.clone(),
dist.clone()
};
for(int i=0; i<NR_OF_CARDS; ++i){
Point p = null;
do{
p = randomPosition();
} while(tmp_cards[p.x][p.y] == 0);
tmp_cards[p.x][p.y]--;
cards.add(new Card(p.x, (p.y + 1)));
}
}
private boolean checkValidMove(){
if(selectedCards == 0) return false;
if(!hintAvailable() && (useColor || useValue)) return false;
if((trashCard || placeCard) && selectedCards == 1) return true;
int countCards = 0;
for(int i=0; i<CARDS_PER_PLAYER; ++i){
AbstractPlayer p = players[selectedPlayer];
if(useColor){
if(p.getCard(i).getColorInt() == chosenColor) countCards++;
} else if(useValue){
if(p.getCard(i).getValue() == chosenValue) countCards++;
}
}
return (countCards == selectedCards);
}
private void createUI(){
mainFrame = new JFrame("Hanabi");
mainFrame.setSize(1000, 1000);
mainFrame.setLocation(0, 0);
mainFrame.setLayout(new BorderLayout());
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.getContentPane().setBackground(Color.black);
mainFrame.setVisible(true);
gamePanel = new JPanel();
gamePanel.setLayout(new BoxLayout(gamePanel, BoxLayout.Y_AXIS));
GridLayout deckLayout = new GridLayout(COLORS, 5);
deckPanel = new JPanel(deckLayout);
deckPanel.setBackground(Color.black);
deckUI = new JLabel[COLORS][5];
for(int i=0; i<COLORS; ++i){
for(int j=0; j<5; ++j){
JLabel tmp = new JLabel("Not set");
tmp.setBackground(Color.black);
tmp.setForeground(Color.white);
deckUI[i][j] = tmp;
deckPanel.add(deckUI[i][j]);
}
}
hintPanel = new JPanel();
thunderPanel = new JPanel();
buttonPanel = new JPanel();
colorButton = new JButton("Color");
valueButton = new JButton("Value");
nextMove = new JButton("Next");
placeCardButton = new JButton("Place");
trashCardButton = new JButton("Trash");
buttonPanel.add(colorButton);
buttonPanel.add(valueButton);
buttonPanel.add(nextMove);
buttonPanel.add(placeCardButton);
buttonPanel.add(trashCardButton);
mainFrame.add(gamePanel, BorderLayout.CENTER);
gamePanel.add(hintPanel);
gamePanel.add(thunderPanel);
gamePanel.add(buttonPanel);
gamePanel.add(deckPanel);
hintUI = new JLabel[MAX_HINTS];
for(int i=0; i<MAX_HINTS; ++i){
JLabel tmp = new JLabel();
tmp.setText("1");
tmp.setBackground(Color.white);
tmp.setName("Hint_" + i);
hintPanel.add(tmp);
hintUI[i] = tmp;
}
thunderUI = new JLabel[MAX_THUNDERS];
for(int i=0;i<MAX_THUNDERS; ++i){
JLabel tmp = new JLabel();
tmp.setText("0");
tmp.setBackground(Color.cyan);
tmp.setName("Thunder_" + i);
thunderPanel.add(tmp);
thunderUI[i] = tmp;
}
colorButton.addMouseListener(new MouseListener(){
@Override
public void mouseReleased(MouseEvent e) {
if(!hintAvailable()){
System.out.println("No hints left!");
return;
}
if(selectedCards > 0){
System.out.println("Please deselect all cards first");
return;
}
useColor = true;
useValue = false;
placeCard = false;
trashCard = false;
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseClicked(MouseEvent e) {
}
});
valueButton.addMouseListener(new MouseListener(){
@Override
public void mouseReleased(MouseEvent e) {
if(!hintAvailable()){
System.out.println("No hints left!");
return;
}
if(selectedCards > 0){
System.out.println("Please deselect all cards first");
return;
}
useValue = true;
useColor = false;
placeCard = false;
trashCard = false;
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseClicked(MouseEvent e) {
}
});
nextMove.addMouseListener(new MouseListener(){
@Override
public void mouseReleased(MouseEvent e) {
if(!checkValidMove()){
System.out.println("Please select all cards of the selected color/value");
return;
}
int selCardIndex = 0;
for(int i=0; i<CARDS_PER_PLAYER; ++i){
SwingPlayer sp = (SwingPlayer) players[selectedPlayer];
JLabel card = sp.getUiCard(i);
String from = "(from Player " + currentPlayer + ")";
if(card.getBackground() == Color.pink){
selCardIndex = i;
card.setBackground(Color.black);
if(useColor){
String color = "- " + intColorToText(chosenColor);
sp.setCardInfo(i, sp.getCardInfo(i) + color + " " + from + "\n");
} else if(useValue){
String value = "- is " + chosenValue;
sp.setCardInfo(i, sp.getCardInfo(i) + value + " " + from + "\n");
}
} else {
if(useColor){
String color = "- not " + intColorToText(chosenColor);
sp.setCardInfo(i, sp.getCardInfo(i) + color + " " + from + "\n");
} else if(useValue){
String value = "- is not " + chosenValue;
sp.setCardInfo(i, sp.getCardInfo(i) + value + " " + from + "\n");
}
}
}
if(useColor || useValue){
hintUI[hints-1].setText("0");
hints--;
} else if(trashCard){
moveCardToTrash(selCardIndex);
if(hints != MAX_HINTS){
hintUI[hints].setText("1");
hints++;
if(hints > MAX_HINTS) hints = MAX_HINTS;
}
} else if(placeCard){
Card c = players[currentPlayer].getCard(selCardIndex);
int color = c.getColorInt();
int value = c.getValue();
int deckValue = deckCounter[color] + 1;
if(deckValue == value){ //place card possible
deckCounter[color]++;
deck[color][value-1] = c;
deckUI[color][value-1].setText(value + "");
deckUI[color][value-1].setForeground(c.getColor());
deckUI[color][value-1].setFont(new Font("Shanghai", Font.PLAIN, 20));
setWonOrLost();
} else { //card too high or too low
thunderUI[thunders++].setText("1");
moveCardToTrash(selCardIndex);
setWonOrLost();
if(lost) return;
}
//dealCard(selCardIndex, currentPlayer);
updateCards(selCardIndex);
}
players[currentPlayer].activeCards();
System.out.println("Player " + currentPlayer + " has finished his move!");
currentPlayer++;
if(currentPlayer == NR_PLAYERS) currentPlayer = 0;
players[currentPlayer].deactiveCards();
resetMoveValues();
System.out.println(CARDS_IN_DECK + " cards left.");
System.out.println(trash.size() + " cards in trash");
System.out.println("Player " + currentPlayer + "'s turn");
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseClicked(MouseEvent e) {
}
});
trashCardButton.addMouseListener(new MouseListener(){
@Override
public void mouseReleased(MouseEvent e) {
if(selectedCards > 0){
System.out.println("Please deselect all cards first");
return;
}
useColor = false;
useValue = false;
placeCard = false;
trashCard = true;
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseClicked(MouseEvent e) {
}
});
placeCardButton.addMouseListener(new MouseListener(){
@Override
public void mouseReleased(MouseEvent e) {
if(selectedCards > 0){
System.out.println("Please deselect all cards first");
return;
}
useColor = false;
useValue = false;
placeCard = true;
trashCard = false;
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseClicked(MouseEvent e) {
}
});
}
private void moveCardToTrash(int index){
trash.add(players[currentPlayer].getCard(index));
updateCards(index);
}
private void updateCards(int index){
dealCard(index, currentPlayer);
players[currentPlayer].setCardInfo(index, "");
Card c = players[currentPlayer].getCard(index);
//JLabel card = ((SwingPlayer) players[currentPlayer]).getUiCard(index);
AbstractPlayer card = players[currentPlayer];
if(c.getValue() == -1){ //dummy card, no more cards
//card.setForeground(Color.orange);
card.setColor(index, 255, 122, 0);
card.setText(index, "No Cards left");
card.unsetListeners(index);
}
}
private void dealCard(int cardID, int playerID){
Card card;
if(CARDS_IN_DECK > 0){
int index = random(CARDS_IN_DECK--);
card = cards.remove(index);
} else {
card = new Card(3, -1);
}
players[playerID].setCard(cardID, card);
}
private void dealCards(){
int dealtCards = 0;
for(; dealtCards < CARDS_PER_PLAYER; ++dealtCards){
for(int i=0; i<NR_PLAYERS; ++i){
int index = random(CARDS_IN_DECK--);
Card card = cards.remove(index);
players[i].setCard(dealtCards, card);
}
}
/*
* PLAYER 0: SOUTH
* PLAYER 1: EAST
* PLAYER 2: NORTH
* PLAYER 3: WEST
*/
for(int i=0; i<NR_PLAYERS; ++i){
JPanel playerContainer = ((SwingPlayer) players[i]).getContainer();
BoxLayout containerLayout = null;
String playerSide = null;
switch(i){
case 0:
playerSide = BorderLayout.SOUTH;
containerLayout = new BoxLayout(playerContainer, BoxLayout.X_AXIS);
break;
case 1:
playerSide = BorderLayout.EAST;
containerLayout = new BoxLayout(playerContainer, BoxLayout.Y_AXIS);
break;
case 2:
playerSide = BorderLayout.NORTH;
containerLayout = new BoxLayout(playerContainer, BoxLayout.X_AXIS);
break;
case 3:
playerSide = BorderLayout.WEST;
containerLayout = new BoxLayout(playerContainer, BoxLayout.Y_AXIS);
break;
}
playerContainer.setLayout(containerLayout);
playerContainer.setBackground(Color.black);
for(int j=0; j<CARDS_PER_PLAYER; ++j){
//JLabel curr = ((SwingPlayer) players[i]).getUiCard(j);
AbstractPlayer curr = players[i];
curr.setName(j, i + "_card" + j);
curr.setSize(j, 50, 50);
}
mainFrame.add(playerContainer, playerSide);
}
}
private boolean hintAvailable(){
return (hints > 0);
}
private void setWonOrLost(){
won = true;
lost = false;
for(int i=0; i<COLORS; ++i){
System.out.println("Deck " + i + ": " + deckCounter[i]);
if(deckCounter[i] != 5){
won = false;
break;
}
}
if(thunders == MAX_THUNDERS){
lost = true;
won = false;
}
if(won) System.out.println("YOU WON!");
if(lost) System.out.println("YOU LOST...");
}
private Point randomPosition(){
Point p = new Point();
p.x = random(5);
p.y = random(5);
return p;
}
private int random(int max){
return (int) (Math.random() * max);
}
public void setSelectedPlayer(int selectedPlayer){
this.selectedPlayer = selectedPlayer;
}
public int getSelectedPlayer(){
return selectedPlayer;
}
public AbstractPlayer getPlayer(int index){
return players[index];
}
public int getCurrentPlayerIndex(){
return currentPlayer;
}
public boolean isTrashCard(){
return trashCard;
}
public boolean isPlaceCard(){
return placeCard;
}
public boolean isUseColor(){
return useColor;
}
public boolean isUseValue(){
return useValue;
}
public int getChosenColor(){
return chosenColor;
}
public void setChosenColor(int chosenColor){
this.chosenColor = chosenColor;
}
public int getChosenValue(){
return chosenValue;
}
public void setChosenValue(int chosenValue){
this.chosenValue = chosenValue;
}
public int getSelectedCards(){
return selectedCards;
}
public void addSelectedCards(){
selectedCards++;
}
public void removeSelectedCards(){
selectedCards--;
}
/*private void printArray(int[][] arr){
for(int j=0; j<arr.length; ++j){
for(int k=0; k<arr[0].length; ++k){
System.out.print(arr[j][k] + ", ");
}
System.out.println("");
}
}*/
}