シェルスクリプトマガジン

test

香川大学SLPからお届け!(Vol.93掲載)

投稿日:2024.11.25 | カテゴリー: コード

著者:原口 莉奈

 私は最近、RPG(Role-Playing Game)の戦闘シーンをC++言語で作成しました。作成には、無償で利用できるゲーム開発用ライブラリ「DXライブラリ」(https://dxlib.xsrv.jp/)を用いています。今回は、その一部であるコマンド選択画面の実装について紹介します。

シェルスクリプトマガジン Vol.93は以下のリンク先でご購入できます。

図2 ビルド用のバッチファイル「build.bat」に記述する内容

g++ -c Main.cpp -DDX_GCC_COMPILE -I"DxLib"
g++ -o game.exe Main.o -L"DxLib" -lgcc -lDxLib -lDxUseCLib ^
 -lDxDrawFunc -ljpeg -lpng -lzlib -ltiff -ltheora_static ^
 -lvorbis_static -lvorbisfile_static -logg_static ^
 -lbulletdynamics -lbulletcollision -lbulletmath -lopusfile ^
 -lopus -lsilk_common -lcelt

図3 「Main.cpp」ファイルに記述するコード

#define WIN_X 256 
#define WIN_Y 224

#include <DxLib.h>

int WINAPI WinMain(
  _In_ HINSTANCE hInstance,
  _In_opt_ HINSTANCE hPrevInstance,
  _In_ LPSTR IpCmdLine,
  _In_ int nShowCmd)
{
  ChangeWindowMode(TRUE);
  DxLib_Init();

  // ウィンドウ初期化
  SetWindowText("game"); // タイトル
  SetGraphMode(WIN_X, WIN_Y, 32); // 解像度と色深度
  SetBackgroundColor(255, 255, 255); // 背景色

  WaitKey();
  DxLib_End();
  return 0;
}

図5 「Main.cpp」ファイルに記述するコード

#define WIN_X 256
#define WIN_Y 224

#include <DxLib.h>
#include "Status.h"
#include "Battle.h"

int WINAPI WinMain(
  _In_ HINSTANCE hInstance,
  _In_opt_ HINSTANCE hPrevInstance,
  _In_ LPSTR IpCmdLine,
  _In_ int nShowCmd)
{
  ChangeWindowMode(TRUE);
  DxLib_Init();

  SetWindowText("game");
  SetGraphMode(WIN_X, WIN_Y, 32);
  SetBackgroundColor(255, 255, 255);
  SetDrawScreen(DX_SCREEN_BACK); // 裏画面描画
  SetWindowSize(1024, 960); // ウィンドウサイズ

  Battle.materialLoad();
  while (ProcessMessage() == 0)
  {
    SetBackgroundColor(0, 0, 0);
    Battle.BattleDraw();
  }
  DxLib_End();
  return 0;
}

図6 「Status.h」ファイルに記述するコード

class BATTLE {
public:
  struct Status {
    char name[50];
    int HP, ATK, DEF; //体力、攻撃力、防御力
  };
  struct Status player = { "player",30, 10, 5 };
  struct Status villain = { "villain",30, 7, 5 };
  struct Status* Player = &player;
  const char* str[4] = { "たたかう", "まもる",
                         "どうぐ", "にげる" };
  const char* item[1] = { "回復" };
  int firstsym = 80;
  int sym = firstsym;
  int sym_limit = firstsym + (4 - 1) * 17;
  int symbol = -1, symnext = 0;
  int pattern = 1;
  int firstarrow = 80;
  int arrow = firstarrow;
  int limit; // firstarrow + (num - 1) * 17
  int a_posi = -1;
  int re = 0;
  int black, white, ms;
  void materialLoad();
  void BattleDraw();
  void one();
  void two();
  void Choices(int x, const char* str[], int n);
private:
};

図7 「Battle.h」ファイルに記述するコード

BATTLE Battle;
void BATTLE::materialLoad() {
  black = GetColor(0, 0, 0);
  white = GetColor(255, 255, 255);
  ms = CreateFontToHandle("MS ゴシック", 10, 6,
                          DX_FONTTYPE_ANTIALIASING_4X4);
}
void BATTLE::Choices(int x, const char* str[], int n) {
  int w = 0;
  for (int i = 0; i < n; i++) {
    DrawBox(x, firstarrow + w,
            x + 80, firstarrow + 16 + w, white, TRUE);
    DrawFormatStringToHandle(x + 5, firstarrow + 5 + w,
                             black, ms, str[i]);
    w += 17;
  }
}
// 初期表示
void BATTLE::one() {
  sym = firstsym;
  pattern = 2;
}
// 矢印の移動
void BATTLE::two() {
  if (symnext == 0) {
    switch (WaitKey()) {
      case KEY_INPUT_DOWN:
        if (sym != sym_limit) sym += 17;
        break;
      case KEY_INPUT_UP:
        if (sym != firstsym)  sym -= 17;
        break;
      case KEY_INPUT_ESCAPE:
        DxLib_End();
        break;	
    }
    if (symbol != -1) symnext++;
  }
}

void BATTLE::BattleDraw() {
  SetDrawScreen(DX_SCREEN_BACK);
  ClearDrawScreen();
  switch(pattern):
  if (pattern == 1) one();
  else if (pattern == 2) two();
  Choices(160, str, 4);
  DrawFormatStringToHandle(144, sym, white, ms, "→");
  ScreenFlip();
}

図9 「Status.h」ファイルにHpDraw()関数の記述を追加

(略)
  void HpDraw();
  void BattleDraw();
(略)

図10 「Battle.h」ファイルのBattleDraw()関数定義部分をこのように書き換える

(略)void BATTLE::HpDraw() {
  DrawBox(180, 160, 250, 184, white, FALSE);
  DrawBox(180, 186, 250, 210, white, FALSE);
  DrawFormatStringToHandle(182, 162, white, ms,
                           "villain\nHP: %d", villain.HP);
  DrawFormatStringToHandle(182, 188, white, ms,
                           "player\nHP:%d", player.HP);
}
void BATTLE::BattleDraw() {
  SetDrawScreen(DX_SCREEN_BACK);
  ClearDrawScreen();
  switch(pattern):
  if (pattern == 1) one();
  else if (pattern == 2) two();
  Choices(160, str, 4);
  DrawFormatStringToHandle(144, sym, white, ms, "→");
  HpDraw();
  ScreenFlip();
}

Markdownを活用する(Vol.93掲載)

投稿日:2024.11.25 | カテゴリー: コード

著者:藤原 由来

本連載では文書の装飾・構造付けを手軽に行える記法であるMarkdownを用いて、さまざまな文書や成果物を作成する方法を紹介します。今回は、プレゼンテーション用のスライドを作成するためのプレゼンテーションアプリ「Marp」について解説します。

シェルスクリプトマガジン Vol.93は以下のリンク先でご購入できます。

図1 Marp用にMarkdownで記述したテキストの例

---
marp: true
---

# 美味しいカレーの作り方  

シェル花子

---

# 材料

- 玉ねぎ
- にんじん
- じゃがいも
- 肉
- カレールー
- 水

---

# 作り方

1. 材料を切る
2. 肉を炒める
3. 野菜を加える
4. 水を加えて煮る
5. カレールーを入れる

図8 見出しレベル1をスライドの区切りにしたMarkdown形式のテキスト例

---
marp: true
headingDivider: 1
---

# 美味しいカレーの作り方  

## シェル花子

# 材料

## ここに
### 材料を書く

# 作り方

## 適当に作る

図11 スライドの背景や文字色を変更したMarkdown形式のテキスト例

---
marp: true
---

# 通常のスライド

---

<!-- 
_backgroundColor: black
_color: white
-->

# 背景が黒く文字が白いスライド

---

<!-- 
_backgroundImage: "linear-gradient(to bottom, #67b8e3, #0288d1)" 
_color: white
-->

# 背景が青いグラデーションのスライド

---

<!-- 
_backgroundImage: url('cat1.png')
-->

# 背景が画像のスライド

図13 背景画像表示とぼかしフィルタ適用のMarkdown形式のテキスト例

---
marp: true
---

# 背景画像を表示する

![bg cover](cat1.png)

---

# 背景画像にぼかしを入れる

![blur bg cover](cat1.png)

図15 背景画像の横並びと縦並びのMarkdown形式のテキスト例

---
marp: true
---

# 背景に横並びに配置

![bg](cat1.png)
![bg](cat1.png)
![bg](cat1.png)

---

# 背景に縦並びに配置

![bg vertical](cat1.png)
![bg](cat1.png)
![bg](cat1.png)

図20 ChatGPTが生成したMarkdown形式のテキスト

---
marp: true
theme: default
paginate: true
backgroundColor: #f0f0f0
---

# 知られざるインドカレー
### シェル花子

---

# 目次
1. 北インド: パニール・バターマサラ  
2. 南インド: チェッティナード・チキンカレー  
3. 西インド: ゴア・フィッシュカレー  
4. 東インド: コサ・マンシャ  
5. 中央インド: ダールバーフライ  
6. 北東インド: アクホニカレー  

---

# 1. 北インド: パニール・バターマサラ

- クリーミーで濃厚なグレイビー
- トマト、バター、クリームを使用
- パニール(カッテージチーズ)入り
- パンジャーブ地方で有名
- ナンやバスマティライスと食べる

---

(略)

Pythonあれこれ(Vol.93掲載)

投稿日:2024.11.25 | カテゴリー: コード

著者:飯尾 淳

本連載では「Pythonを昔から使っているものの、それほど使いこなしてはいない」という筆者が、いろいろな日常業務をPythonで処理することで、立派な「蛇使い」に育つことを目指します。その過程を温かく見守ってください。皆さんと共に勉強していきましょう。第23回では、機械学習ライブラリ「scikit-learn」で何ができるのかを紹介した上で、データを二つのクラスに分類するPythonプログラムを作成します。

シェルスクリプトマガジン Vol.93は以下のリンク先でご購入できます。

図9 テストデータを作成するPythonコード

import pandas as pd
from sklearn.datasets import make_classification
(data, label) = make_classification(n_samples=1000, 
                                    n_features=2, n_classes=2, 
                                    n_informative=2,
                                    n_redundant=0,
                                    random_state=133)
df = pd.DataFrame({'x1':[d[0] for d in data], 
                   'x2':[d[1] for d in data],
                   'label':label})
df.plot.scatter(x='x1', y='x2', 
                c=df['label'].map({0:'blue', 1:'red'}), s=5)

図10 LinearSVCを用いて学習と分類をするPythonコード

from sklearn.svm import LinearSVC
from sklearn.metrics import accuracy_score
clf = LinearSVC(random_state=0, dual='auto', tol=1e-5)
clf.fit(data, label)
accuracy_score(clf.predict(data), label)

図11 分離面を描画するPythonコード

from mlxtend.plotting import plot_decision_regions
plot_decision_regions(data, label, clf=clf)

図13 NuSVCを用いて学習と分類をするPythonコード

from sklearn.svm import NuSVC
clf = NuSVC(nu=0.1, random_state=0)
clf.fit(data, label)
accuracy_score(clf.predict(data), label)

図15 SVCを用いて学習と分類をするPythonコード(その1)

from sklearn.svm import SVC
clf = SVC(gamma=0.1, random_state=0)
clf.fit(data, label)
accuracy_score(clf.predict(data), label)

図17 SVCを用いて学習と分類をするPythonコード(その2)

from sklearn.svm import SVC
clf = SVC(gamma=0.1, random_state=0)
clf.fit(data, label)
accuracy_score(clf.predict(data), label)

特集1 Streamlitで作るデータ分析Webアプリ(Vol.93記載)

投稿日:2024.11.25 | カテゴリー: コード

著者:邑川 真也

「Streamlit」は、OSS(オープンソースソフトウエア)のPython向けフレームワーク(ライブラリ)です。データの可視化機能や分析機能、ダッシュボードなどを備えるWebアプリケーションを、Pythonを使って迅速かつ容易に作成できます。本特集では、さまざまなWebアプリケーションを実際に作成しながら、基本的なデータの可視化方法から、ノーコードでデータ分析を実現する方法まで、Streamlitのさまざまな活用方法を紹介します。

シェルスクリプトマガジン Vol.93は以下のリンク先でご購入できます。

図2 HTMLとCSS、JavaScriptを用いて棒グラフを描くコードの例

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport"
        content="width=device-width, initial-scale=1.0">
  <title>Bar Chart Example</title>
  <style>
    .chart-container {
      width: 70%;
      margin: 0 auto;
    }
  </style>
</head>
<body>
  <div class="chart-container">
    <canvas id="myBarChart"></canvas>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
  <script>
    var ctx = document.getElementById('myBarChart').getContext('2d');
    var myBarChart = new Chart(ctx, {
      type: 'bar',
      data: {
        labels: ['January', 'February', 'March',
                 'April', 'May', 'June', 'July'],
        datasets: [{
          label: 'Sample Data',
          data: [65, 59, 80, 81, 56, 55, 40],
          backgroundColor: 'rgba(54, 162, 235, 0.2)',
          borderColor: 'rgba(54, 162, 235, 1)',
          borderWidth: 1
        }]
      },
      options: {
        scales: {
          y: {
            beginAtZero: true
          }
        }
      }
    });
  </script>
</body>
</html>

図3 Streamlitを用いて棒グラフを描くコードの例

import streamlit as st
import pandas as pd
import altair as alt

data = pd.DataFrame({
    'Month': ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
    'Value': [65, 59, 80, 81, 56, 55, 40]
})
chart = alt.Chart(data).mark_bar().encode(
    x='Month',
    y='Value',
    color=alt.value('steelblue')
)
st.title('Bar Chart Example')
st.altair_chart(chart, use_container_width=True)

図6 シンプルなWebアプリケーションのコード

import streamlit as st

# タイトルを表示
st.title("シェルスクリプトマガジン")

図9 架空の株価データを生成して表示するコード

import streamlit as st
import pandas as pd
import numpy as np
from datetime import datetime, timedelta

# 株価データを生成(仮のデータ)
dates = [datetime.today() - timedelta(days=i) for i in range(14)]
dates.reverse()
data = {
  'Date': dates,
  'Google': np.random.uniform(2700, 3000, 14),
  'Apple': np.random.uniform(140, 160, 14),
  'Meta': np.random.uniform(320, 350, 14),
  'Amazon': np.random.uniform(3300, 3500, 14)
}
# データフレームに変換
df = pd.DataFrame(data)
df.set_index('Date', inplace=True)
# タイトルを表示
st.title("株価データの可視化")
# データフレームの表示
st.dataframe(df)

図14 「data.csv」ファイルに記述するデータ(抜粋)

Case ID,Company,Inquiry Summary,Status,Start Date,Severity
1,Acme Corp,大規模データセットに対するクエリの最適化について,Open,2024-05-19,Sev4
2,Globex Inc,DWHのベストプラクティスについて,Open,2024-05-26,Sev3
3,Globex Inc,データロード時のエラー,Open,2024-05-21,Sev3
4,Soylent Corp,新機能の有効化について,Open,2024-05-22,Sev2
5,Soylent Corp,レプリケートに失敗しています,Open,2024-05-22,Sev3
(略)

図15 ダッシュボードアプリのコード

import streamlit as st
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# ページ設定
st.set_page_config(
  page_title="サポートデスクダッシュボード",
  initial_sidebar_state="expanded",
  layout="wide"
)
st.title("サポートデスクダッシュボード")
# チケット一覧を表示
st.subheader("チケット一覧")
# データ読み込み
df = pd.read_csv("data.csv")

with st.container(border=True, height=100):
  filter1, filter2 = st.columns(2)
with filter1:
  # ステータスによるフィルタ
  status_list = df['Status'].unique()
  selected_status = st.multiselect("ステータス",
                                   options=status_list,
                                   default=status_list)
with filter2:
  # 重要度によるフィルタ
  severity_list = df['Severity'].unique()
  selected_severity = st.multiselect("重要度",
                                     options=severity_list,
                                     default=severity_list)
# フィルタを適用
if selected_status or selected_severity:
  df = df[(df['Status'].isin(selected_status) &
           df['Severity'].isin(selected_severity))]

# データを表示
st.dataframe(df, use_container_width=True)
# グラフを横並びに表示するレイアウトを作成
st.markdown("")
col1, col2  = st.columns(2)
# 縦棒グラフでステータスの数を表示
with col1:
  st.subheader("チケットごとのステータス集計")
  fig, ax = plt.subplots()
  status_counts = df["Status"].value_counts()
  ax.bar(status_counts.index, status_counts.values,
         color="skyblue")
  ax.set_xlabel("Status")
  ax.set_ylabel("Count")
  ax.set_title("Tickets by Status")
  with st.container(border=True):
    st.pyplot(fig)
# 縦棒グラフで重要度の数を表示
with col2:
  st.subheader("チケットごとの重要度集計")
  severity_counts = df["Severity"].value_counts()
  fig, ax = plt.subplots()
  ax.bar(severity_counts.index, severity_counts.values, color="coral")
  ax.set_xlabel("Severity")
  ax.set_ylabel("Count")
  ax.set_title("Tickets by Severity")
  with st.container(border=True):
    st.pyplot(fig)

# CSVダウンロード
csv = df.to_csv(index=False)
st.download_button(
  label="Download CSV",
  data=csv,
  file_name='sample_data.csv',
  mime='text/csv'
)

図17 「config.toml」ファイルに記述するテーマ設定の例

[theme]
primaryColor = "#F14143"              # プライマリカラー
backgroundColor = "#101216"           # 背景色
secondaryBackgroundColor = "#191B20"  # セカンダリ背景色
textColor = "#F9F9F9"                 # テキストカラー
font = "sans serif"                   # フォント

図18 「pygw_test.py」ファイルに記述するコード

from pygwalker.api.streamlit import StreamlitRenderer
import pandas as pd
import streamlit as st

# Streamlitの画面幅を調整
st.set_page_config(
  page_title="Use Pygwalker In Streamlit",
  layout="wide"
)
# データの取得
df = pd.read_csv("https://kanaries-app.s3.ap-northeast-1.amazonaws.com/public-datasets/bike_sharing_dc.csv")
# PYGWalkerによる可視化 
pyg_app = StreamlitRenderer(df)
pyg_app.explorer()

レポート1(Vol.93掲載)

投稿日:2024.11.25 | カテゴリー: コード

著者:末安 泰三

クジラ飛行机氏は2024年11月7日、手軽にGUIを作成可能なPythonライブラリ「TkEasyGUI」のバージョン1.0系列をリリースした。バージョン1.0系列では、複数項目を入力できるフォームダイアログが追加されるなどの機能拡充やバグ修正が施されている。

シェルスクリプトマガジン Vol.93は以下のリンク先でご購入できます。

図1 個人情報を入力させるウィンドウを作成するコードの例

import TkEasyGUI as eg

layout = [
  [eg.Text('氏名', size=(15, 1)), eg.InputText()],
  [eg.Text('住所', size=(15, 1)), eg.InputText()],
  [eg.Text('電話番号', size=(15, 1)), eg.InputText()],
  [eg.Text()],
  [eg.Button('OK'), eg.Button('Cancel')]
]
with eg.Window('個人情報を入力', layout) as window:
  for event in window.event_iter():
    pass

図3 フォームダイアログを表示するコードの例

iimport TkEasyGUI as eg

form = eg.popup_get_form(["氏名", "住所", "電話番号"],
                         title="個人情報の入力")

シェルスクリプトマガジンvol.93 Web掲載記事まとめ

投稿日:2024.11.25 | カテゴリー: コード

004 レポート Python用の国産GUIライブラリ公開 コード掲載
005 レポート Open Source Summit + AI_dev開催
製品レビュー 組み込み機器「ラズパイ AI HAT+」
007 NEWS FLASH
008 特集1 Streamlitで作るデータ分析Webアプリ/邑川真也 コード掲載
018 特集2 Oracleデータベース入門/宮本拓弥、百木和美、武井菜々子、北村海人
034 イベントレポート「第35回 プロコン」/塩田哲也
036 Raspberry Pi Pico W/WHで始める電子工作/米田聡
040 Pythonあれこれ/飯尾淳 コード掲載
046 Markdownを活用する/藤原由来 コード掲載
056 中小企業手作りIT化奮戦記/菅雄一
062 香川大学SLPからお届け!/原口莉奈 コード掲載
068 これだけは覚えておきたいLinuxコマンド/大津真
076 Techパズル/gori.sh
077 コラム「仕組みを作るSE」/シェル魔人

Vol.93

投稿日:2024.11.25 | カテゴリー: バックナンバー

 産業界のDX(デジタルトランスフォーメーション)が叫ばれている現在、さまざまなデータの価値に注目が集まっています。それらのデータをグラフなどで可視化できるオープンソースのPythonフレームワーク(ライブラリ)が「Streamlit」です。特集1では、初心者にも分かりやすいように、実際に手を動かすという形で、Streamlitによるグラフ作成方法を紹介しています。
 特集2では、オラクルのクラウドサービス「Oracle Cloud Infrastructure」(OCI)上で動作するデータベース管理システム「Oracleデータベース」を解説しています。OCI上でもOracleデータベースの全機能が利用できます。さらに「Autonomous Database」というサービスを利用すれば、日常的な運用管理を自動化できます。
 このほか、連載「Pythonあれこれ」では、機械学習ライブラリ「scikit-learn」について紹介しています。また、イベントレポートとして「第35回 全国高等専門学校プログラミングコンテスト」も掲載しています。
 今回も読み応え十分のシェルスクリプトマガジン Vol.93。お見逃しなく!

※記事掲載のコードはこちら。記事の補足情報はこちら

※読者アンケートはこちら

Vol.93 補足情報

投稿日:2024.11.20 | カテゴリー: コード

特集1 Streamlitで作るデータ分析Webアプリ

p.13の図15で示したコードで使用するデータファイル「data.csv」をここからダウンロードできます。

連載 香川大学SLPからお届け!

記事で紹介したコードを拡張して、コンピュータとの簡単な対戦ができるゲームを作成しました。ソースコードをまとめたアーカイブファイルはここからダウンロードできます。

情報は随時更新致します。

  • shell-mag ブログの 2024年11月 のアーカイブを表示しています。

  • -->